prasb commited on
Commit
964d8a4
·
verified ·
1 Parent(s): 06f9e1c

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +2 -0
  2. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/SimpleITK/__pycache__/__init__.cpython-38.pyc +0 -0
  3. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/SimpleITK/__pycache__/extra.cpython-38.pyc +0 -0
  4. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/SimpleITK/docs/LICENSE +202 -0
  5. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/SimpleITK/docs/NOTICE +9 -0
  6. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/SimpleITK/docs/Readme.md +87 -0
  7. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif-BoldItalic.ttf +3 -0
  8. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif.ttf +3 -0
  9. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/__pycache__/__init__.cpython-38.pyc +0 -0
  10. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/builtins/__init__.py +72 -0
  11. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/builtins/misc.py +94 -0
  12. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/builtins/noniterators.py +272 -0
  13. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/translation/__pycache__/__init__.cpython-38.pyc +0 -0
  14. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/types/__init__.py +29 -0
  15. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/types/olddict.py +96 -0
  16. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/types/oldstr.py +135 -0
  17. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/utils/__init__.py +97 -0
  18. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/__init__.cpython-38.pyc +0 -0
  19. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/_load_gpu_decoder.cpython-38.pyc +0 -0
  20. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/_video_opt.cpython-38.pyc +0 -0
  21. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/image.cpython-38.pyc +0 -0
  22. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/video.cpython-38.pyc +0 -0
  23. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/video_reader.cpython-38.pyc +0 -0
  24. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/_video_opt.py +505 -0
  25. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/image.py +257 -0
  26. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/video.py +415 -0
  27. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/__pycache__/_meta.cpython-38.pyc +0 -0
  28. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/__pycache__/alexnet.cpython-38.pyc +0 -0
  29. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/__pycache__/feature_extraction.cpython-38.pyc +0 -0
  30. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/__pycache__/mobilenetv2.cpython-38.pyc +0 -0
  31. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/detection/_utils.py +538 -0
  32. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/detection/anchor_utils.py +268 -0
  33. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/detection/generalized_rcnn.py +118 -0
  34. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/detection/ssdlite.py +339 -0
  35. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/detection/transform.py +309 -0
  36. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/optical_flow/__pycache__/__init__.cpython-38.pyc +0 -0
  37. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/optical_flow/__pycache__/_utils.cpython-38.pyc +0 -0
  38. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/optical_flow/__pycache__/raft.cpython-38.pyc +0 -0
  39. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/__init__.cpython-38.pyc +0 -0
  40. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/googlenet.cpython-38.pyc +0 -0
  41. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/inception.cpython-38.pyc +0 -0
  42. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/mobilenet.cpython-38.pyc +0 -0
  43. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/mobilenetv2.cpython-38.pyc +0 -0
  44. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/mobilenetv3.cpython-38.pyc +0 -0
  45. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/__init__.cpython-38.pyc +0 -0
  46. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/_utils.cpython-38.pyc +0 -0
  47. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/deeplabv3.cpython-38.pyc +0 -0
  48. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/fcn.cpython-38.pyc +0 -0
  49. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/lraspp.cpython-38.pyc +0 -0
  50. my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/segmentation.cpython-38.pyc +0 -0
.gitattributes CHANGED
@@ -390,3 +390,5 @@ my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/
390
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans-Bold.ttf filter=lfs diff=lfs merge=lfs -text
391
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneral.ttf filter=lfs diff=lfs merge=lfs -text
392
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-Bold.ttf filter=lfs diff=lfs merge=lfs -text
 
 
 
390
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans-Bold.ttf filter=lfs diff=lfs merge=lfs -text
391
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/STIXGeneral.ttf filter=lfs diff=lfs merge=lfs -text
392
  my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-Bold.ttf filter=lfs diff=lfs merge=lfs -text
393
+ my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif-BoldItalic.ttf filter=lfs diff=lfs merge=lfs -text
394
+ my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif.ttf filter=lfs diff=lfs merge=lfs -text
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/SimpleITK/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (278 Bytes). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/SimpleITK/__pycache__/extra.cpython-38.pyc ADDED
Binary file (12.4 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/SimpleITK/docs/LICENSE ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/SimpleITK/docs/NOTICE ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ SimpleITK
2
+
3
+ Copyright 2010-2019 Insight Software Consortium
4
+ Copyright 2020 NumFOCUS
5
+
6
+ This software is distributed under the
7
+ Apache 2.0 License.
8
+
9
+ See LICENSE file for details.
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/SimpleITK/docs/Readme.md ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SimpleITK
2
+ =========
3
+
4
+ | | CircleCI | ReadTheDocs | AzurePipelines |
5
+ |:-------:|:---------:|:-------------:|:-------------:|
6
+ | release | [![CircleCI](https://circleci.com/gh/SimpleITK/SimpleITK/tree/release.svg?style=shield)](https://circleci.com/gh/SimpleITK/SimpleITK/tree/release) | [![ReadTheDoc](https://readthedocs.org/projects/simpleitk/badge/?version=release)](http://simpleitk.readthedocs.io/en/release/) | [![Build Status](https://dev.azure.com/SimpleITK-DevOps/SimpleITK/_apis/build/status/SimpleITK.SimpleITK?branchName=release)](https://dev.azure.com/SimpleITK-DevOps/SimpleITK/_build/latest?definitionId=2&branchName=release) |
7
+ | master | [![CircleCI](https://circleci.com/gh/SimpleITK/SimpleITK/tree/master.svg?style=shield)](https://circleci.com/gh/SimpleITK/SimpleITK/tree/master) | [![ReadTheDoc](https://readthedocs.org/projects/simpleitk/badge/?version=master)](http://simpleitk.readthedocs.io/en/master/) | [![Build Status](https://dev.azure.com/SimpleITK-DevOps/SimpleITK/_apis/build/status/SimpleITK.SimpleITK?branchName=master)](https://dev.azure.com/SimpleITK-DevOps/SimpleITK/_build/latest?definitionId=2&branchName=master) |
8
+
9
+
10
+ SimpleITK is an image analysis toolkit with a large number of components supporting general filtering operations, image segmentation and registration. It is built on top of the Insight Segmentation and Registration Toolkit [ITK](https://www.itk.org) with the intent of providing a simplified interface to ITK. SimpleITK itself is written in C++ but is available for a large number of programming languages. Currently these include:
11
+
12
+ * [Python](http://www.python.org)
13
+ * [R](https://www.r-project.org)
14
+ * [Java](http://www.java.com)
15
+ * [C#](http://msdn.microsoft.com/en-us/vcsharp/default.aspx)
16
+ * [Lua](http://www.lua.org)
17
+ * [TCL](https://www.tcl.tk/)
18
+ * [Ruby](https://www.ruby-lang.org/en/)
19
+
20
+
21
+ Wrapping of the C++ code is accomplished through [SWIG](http://www.swig.org), in principle, any language wrapped by SWIG should be applicable to SimpleITK.
22
+
23
+ Unlike ITK's support of n-dimensional spatio-temporal images, SimpleITK supports 2D, 3D and 4D images. The dimensionality refers to spatio-temporal dimensions, the voxels can be n-dimensional vectors.
24
+
25
+ SimpleITK is licensed under the [Apache License](http://www.opensource.org/licenses/apache2.0.php).
26
+
27
+ Acknowledgments
28
+ --------------
29
+ SimpleITK development has been supported by:
30
+
31
+ * The Intramural Research Program of the National Institutes of Health, National Institute of Allergy and Infectious Diseases.
32
+
33
+ * The US National Library of Medicine under the American Recovery and Reinvestment Act (ARRA) and under the Intramural Research Program of the U.S. National Institutes of Health.
34
+
35
+ * The Insight Software Consortium and the ITK user and developer communities.
36
+
37
+
38
+ License and Copyright
39
+ ---------------------
40
+
41
+ The SimpleITK project is part of the [Insight Software Consortium](https://www.insightsoftwareconsortium.org/)(ISC) a non-profit educational consortium dedicated to promoting and maintaining open-source, freely available software for bio-medical image analysis. The copyright is held by [NumFOCUS](https://numfocus.org/). The SimpleITK software is distributed under the [Apache License 2.0](https://github.com/SimpleITK/SimpleITK/blob/master/LICENSE).
42
+
43
+
44
+ How to Cite
45
+ --------
46
+
47
+ If you found SimpleITK useful in your research, support our efforts by citing
48
+ the relevant publication(s):
49
+
50
+ R. Beare, B. C. Lowekamp, Z. Yaniv, "Image Segmentation, Registration and
51
+ Characterization in R with SimpleITK", *J Stat Softw*, 86(8), https://doi.org/10.18637/jss.v086.i08, 2018.
52
+
53
+ Z. Yaniv, B. C. Lowekamp, H. J. Johnson, R. Beare, "SimpleITK Image-Analysis Notebooks: a Collaborative Environment for Education and Reproducible Research", *J Digit Imaging.*, 31(3): 290-303, https://doi.org/10.1007/s10278-017-0037-8, 2018.
54
+
55
+ B. C. Lowekamp, D. T. Chen, L. Ibáñez, D. Blezek, "The Design of SimpleITK", *Front. Neuroinform.*, 7:45. https://doi.org/10.3389/fninf.2013.00045, 2013.
56
+
57
+ Documentation
58
+ -------------
59
+ With massive libraries like SimpleITK, good documentation is a must. The documentation for SimpleITK is split up into multiple levels:
60
+ 1. [API Documentation](https://simpleitk.org/doxygen/latest/html/) - This contains class and function documentation. The descriptions for functions and classes are primarily borrowed from the original ITK C++ classes.
61
+ 2. [SimpleITK Documentation](http://simpleitk.readthedocs.io/en/master/) - This site contains high-level guides (fundamental SimpleITK concepts, common conventions, etc.), details with respect to the toolkit's binary distributions, instructions for building the toolkit, as well as SimpleITK examples in all supported programming languages. [This site replaced the
62
+ [SimpleITK Wiki](https://itk.org/Wiki/SimpleITK) which is mostly of interest for historical reasons.]
63
+ 3. [Juypyter Notebook Repository](http://insightsoftwareconsortium.github.io/SimpleITK-Notebooks/) - This repository contains a collection of Jupyter Notebooks illustrating the use of SimpleITK for educational and research activities. The notebooks demonstrate the use of SimpleITK for interactive image analysis using the Python and R programming languages. Recommended reading, if you are starting with SimpleITK.
64
+
65
+
66
+ Support
67
+ -------
68
+
69
+ SimpleITK provides access to most of the ITK components, but not all. If you are looking for something specific and can't find it, open an issue on GitHub or ask for support on the [forum](https://discourse.itk.org).
70
+
71
+ Report an Issue
72
+ ---------------
73
+
74
+ Help us improve SimpleITK by reporting issues you encounter. When you report an error, you allow us to address your specific problem, but more importantly you are helping all of the SimpleITK community.
75
+
76
+ **Thank you for helping making SimpleITK better!**
77
+
78
+ All issues are reported and managed on the [project's GitHub issue tracker](https://github.com/SimpleITK/SimpleITK/issues). When reporting an issue, please provide as much information as possible to enable us to reproduce the problem.
79
+
80
+ The following information will allow us to address your issue in a timely manner:
81
+ 1. Error message (copy & pasted) and focused description of the problem.
82
+ 2. Operating system, and version (e.g. OSX 10.11.6).
83
+ 3. Programming language, and version (e.g. Python 2.7.14, R 3.2.3).
84
+ 4. Version of SimpleITK (e.g. 1.1.0), just invoke the SimpleITK Version() function.
85
+ 5. How did you install SimpleITK, binary distribution (e.g. conda install -c simpleitk simpleitk), or built it from source (e.g. devtools::install_github("SimpleITK/SimpleITKRInstaller")).
86
+ 6. A minimal working example which causes the error.
87
+ 7. If your code requires input, possibly point to a minimal sized input image.
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif-BoldItalic.ttf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d93efec7a9d2e826768d1a2ee95b95870e15e29599a84f3484af1de1cec2e181
3
+ size 347064
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSerif.ttf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:107244956e9962b9e96faccdc551825e0ae0898ae13737133e1b921a2fd35ffa
3
+ size 379740
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (3.1 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/builtins/__init__.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ A resurrection of some old functions from Python 2 for use in Python 3. These
3
+ should be used sparingly, to help with porting efforts, since code using them
4
+ is no longer standard Python 3 code.
5
+
6
+ This module provides the following:
7
+
8
+ 1. Implementations of these builtin functions which have no equivalent on Py3:
9
+
10
+ - apply
11
+ - chr
12
+ - cmp
13
+ - execfile
14
+
15
+ 2. Aliases:
16
+
17
+ - intern <- sys.intern
18
+ - raw_input <- input
19
+ - reduce <- functools.reduce
20
+ - reload <- imp.reload
21
+ - unichr <- chr
22
+ - unicode <- str
23
+ - xrange <- range
24
+
25
+ 3. List-producing versions of the corresponding Python 3 iterator-producing functions:
26
+
27
+ - filter
28
+ - map
29
+ - range
30
+ - zip
31
+
32
+ 4. Forward-ported Py2 types:
33
+
34
+ - basestring
35
+ - dict
36
+ - str
37
+ - long
38
+ - unicode
39
+
40
+ """
41
+
42
+ from future.utils import PY3
43
+ from past.builtins.noniterators import (filter, map, range, reduce, zip)
44
+ # from past.builtins.misc import (ascii, hex, input, oct, open)
45
+ if PY3:
46
+ from past.types import (basestring,
47
+ olddict as dict,
48
+ oldstr as str,
49
+ long,
50
+ unicode)
51
+ else:
52
+ from __builtin__ import (basestring, dict, str, long, unicode)
53
+
54
+ from past.builtins.misc import (apply, chr, cmp, execfile, intern, oct,
55
+ raw_input, reload, unichr, unicode, xrange)
56
+ from past import utils
57
+
58
+
59
+ if utils.PY3:
60
+ # We only import names that shadow the builtins on Py3. No other namespace
61
+ # pollution on Py3.
62
+
63
+ # Only shadow builtins on Py3; no new names
64
+ __all__ = ['filter', 'map', 'range', 'reduce', 'zip',
65
+ 'basestring', 'dict', 'str', 'long', 'unicode',
66
+ 'apply', 'chr', 'cmp', 'execfile', 'intern', 'raw_input',
67
+ 'reload', 'unichr', 'xrange'
68
+ ]
69
+
70
+ else:
71
+ # No namespace pollution on Py2
72
+ __all__ = []
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/builtins/misc.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import unicode_literals
2
+
3
+ import inspect
4
+
5
+ from future.utils import PY2, PY3, exec_
6
+
7
+ if PY2:
8
+ from collections import Mapping
9
+ else:
10
+ from collections.abc import Mapping
11
+
12
+ if PY3:
13
+ import builtins
14
+ from collections.abc import Mapping
15
+
16
+ def apply(f, *args, **kw):
17
+ return f(*args, **kw)
18
+
19
+ from past.builtins import str as oldstr
20
+
21
+ def chr(i):
22
+ """
23
+ Return a byte-string of one character with ordinal i; 0 <= i <= 256
24
+ """
25
+ return oldstr(bytes((i,)))
26
+
27
+ def cmp(x, y):
28
+ """
29
+ cmp(x, y) -> integer
30
+
31
+ Return negative if x<y, zero if x==y, positive if x>y.
32
+ """
33
+ return (x > y) - (x < y)
34
+
35
+ from sys import intern
36
+
37
+ def oct(number):
38
+ """oct(number) -> string
39
+
40
+ Return the octal representation of an integer
41
+ """
42
+ return '0' + builtins.oct(number)[2:]
43
+
44
+ raw_input = input
45
+ from imp import reload
46
+ unicode = str
47
+ unichr = chr
48
+ xrange = range
49
+ else:
50
+ import __builtin__
51
+ from collections import Mapping
52
+ apply = __builtin__.apply
53
+ chr = __builtin__.chr
54
+ cmp = __builtin__.cmp
55
+ execfile = __builtin__.execfile
56
+ intern = __builtin__.intern
57
+ oct = __builtin__.oct
58
+ raw_input = __builtin__.raw_input
59
+ reload = __builtin__.reload
60
+ unicode = __builtin__.unicode
61
+ unichr = __builtin__.unichr
62
+ xrange = __builtin__.xrange
63
+
64
+
65
+ if PY3:
66
+ def execfile(filename, myglobals=None, mylocals=None):
67
+ """
68
+ Read and execute a Python script from a file in the given namespaces.
69
+ The globals and locals are dictionaries, defaulting to the current
70
+ globals and locals. If only globals is given, locals defaults to it.
71
+ """
72
+ if myglobals is None:
73
+ # There seems to be no alternative to frame hacking here.
74
+ caller_frame = inspect.stack()[1]
75
+ myglobals = caller_frame[0].f_globals
76
+ mylocals = caller_frame[0].f_locals
77
+ elif mylocals is None:
78
+ # Only if myglobals is given do we set mylocals to it.
79
+ mylocals = myglobals
80
+ if not isinstance(myglobals, Mapping):
81
+ raise TypeError('globals must be a mapping')
82
+ if not isinstance(mylocals, Mapping):
83
+ raise TypeError('locals must be a mapping')
84
+ with open(filename, "rb") as fin:
85
+ source = fin.read()
86
+ code = compile(source, filename, "exec")
87
+ exec_(code, myglobals, mylocals)
88
+
89
+
90
+ if PY3:
91
+ __all__ = ['apply', 'chr', 'cmp', 'execfile', 'intern', 'raw_input',
92
+ 'reload', 'unichr', 'unicode', 'xrange']
93
+ else:
94
+ __all__ = []
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/builtins/noniterators.py ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This module is designed to be used as follows::
3
+
4
+ from past.builtins.noniterators import filter, map, range, reduce, zip
5
+
6
+ And then, for example::
7
+
8
+ assert isinstance(range(5), list)
9
+
10
+ The list-producing functions this brings in are::
11
+
12
+ - ``filter``
13
+ - ``map``
14
+ - ``range``
15
+ - ``reduce``
16
+ - ``zip``
17
+
18
+ """
19
+
20
+ from __future__ import division, absolute_import, print_function
21
+
22
+ from itertools import chain, starmap
23
+ import itertools # since zip_longest doesn't exist on Py2
24
+ from past.types import basestring
25
+ from past.utils import PY3
26
+
27
+
28
+ def flatmap(f, items):
29
+ return chain.from_iterable(map(f, items))
30
+
31
+
32
+ if PY3:
33
+ import builtins
34
+
35
+ # list-producing versions of the major Python iterating functions
36
+ def oldfilter(*args):
37
+ """
38
+ filter(function or None, sequence) -> list, tuple, or string
39
+
40
+ Return those items of sequence for which function(item) is true.
41
+ If function is None, return the items that are true. If sequence
42
+ is a tuple or string, return the same type, else return a list.
43
+ """
44
+ mytype = type(args[1])
45
+ if isinstance(args[1], basestring):
46
+ return mytype().join(builtins.filter(*args))
47
+ elif isinstance(args[1], (tuple, list)):
48
+ return mytype(builtins.filter(*args))
49
+ else:
50
+ # Fall back to list. Is this the right thing to do?
51
+ return list(builtins.filter(*args))
52
+
53
+ # This is surprisingly difficult to get right. For example, the
54
+ # solutions here fail with the test cases in the docstring below:
55
+ # http://stackoverflow.com/questions/8072755/
56
+ def oldmap(func, *iterables):
57
+ """
58
+ map(function, sequence[, sequence, ...]) -> list
59
+
60
+ Return a list of the results of applying the function to the
61
+ items of the argument sequence(s). If more than one sequence is
62
+ given, the function is called with an argument list consisting of
63
+ the corresponding item of each sequence, substituting None for
64
+ missing values when not all sequences have the same length. If
65
+ the function is None, return a list of the items of the sequence
66
+ (or a list of tuples if more than one sequence).
67
+
68
+ Test cases:
69
+ >>> oldmap(None, 'hello world')
70
+ ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
71
+
72
+ >>> oldmap(None, range(4))
73
+ [0, 1, 2, 3]
74
+
75
+ More test cases are in test_past.test_builtins.
76
+ """
77
+ zipped = itertools.zip_longest(*iterables)
78
+ l = list(zipped)
79
+ if len(l) == 0:
80
+ return []
81
+ if func is None:
82
+ result = l
83
+ else:
84
+ result = list(starmap(func, l))
85
+
86
+ # Inspect to see whether it's a simple sequence of tuples
87
+ try:
88
+ if max([len(item) for item in result]) == 1:
89
+ return list(chain.from_iterable(result))
90
+ # return list(flatmap(func, result))
91
+ except TypeError as e:
92
+ # Simple objects like ints have no len()
93
+ pass
94
+ return result
95
+
96
+ ############################
97
+ ### For reference, the source code for Py2.7 map function:
98
+ # static PyObject *
99
+ # builtin_map(PyObject *self, PyObject *args)
100
+ # {
101
+ # typedef struct {
102
+ # PyObject *it; /* the iterator object */
103
+ # int saw_StopIteration; /* bool: did the iterator end? */
104
+ # } sequence;
105
+ #
106
+ # PyObject *func, *result;
107
+ # sequence *seqs = NULL, *sqp;
108
+ # Py_ssize_t n, len;
109
+ # register int i, j;
110
+ #
111
+ # n = PyTuple_Size(args);
112
+ # if (n < 2) {
113
+ # PyErr_SetString(PyExc_TypeError,
114
+ # "map() requires at least two args");
115
+ # return NULL;
116
+ # }
117
+ #
118
+ # func = PyTuple_GetItem(args, 0);
119
+ # n--;
120
+ #
121
+ # if (func == Py_None) {
122
+ # if (PyErr_WarnPy3k("map(None, ...) not supported in 3.x; "
123
+ # "use list(...)", 1) < 0)
124
+ # return NULL;
125
+ # if (n == 1) {
126
+ # /* map(None, S) is the same as list(S). */
127
+ # return PySequence_List(PyTuple_GetItem(args, 1));
128
+ # }
129
+ # }
130
+ #
131
+ # /* Get space for sequence descriptors. Must NULL out the iterator
132
+ # * pointers so that jumping to Fail_2 later doesn't see trash.
133
+ # */
134
+ # if ((seqs = PyMem_NEW(sequence, n)) == NULL) {
135
+ # PyErr_NoMemory();
136
+ # return NULL;
137
+ # }
138
+ # for (i = 0; i < n; ++i) {
139
+ # seqs[i].it = (PyObject*)NULL;
140
+ # seqs[i].saw_StopIteration = 0;
141
+ # }
142
+ #
143
+ # /* Do a first pass to obtain iterators for the arguments, and set len
144
+ # * to the largest of their lengths.
145
+ # */
146
+ # len = 0;
147
+ # for (i = 0, sqp = seqs; i < n; ++i, ++sqp) {
148
+ # PyObject *curseq;
149
+ # Py_ssize_t curlen;
150
+ #
151
+ # /* Get iterator. */
152
+ # curseq = PyTuple_GetItem(args, i+1);
153
+ # sqp->it = PyObject_GetIter(curseq);
154
+ # if (sqp->it == NULL) {
155
+ # static char errmsg[] =
156
+ # "argument %d to map() must support iteration";
157
+ # char errbuf[sizeof(errmsg) + 25];
158
+ # PyOS_snprintf(errbuf, sizeof(errbuf), errmsg, i+2);
159
+ # PyErr_SetString(PyExc_TypeError, errbuf);
160
+ # goto Fail_2;
161
+ # }
162
+ #
163
+ # /* Update len. */
164
+ # curlen = _PyObject_LengthHint(curseq, 8);
165
+ # if (curlen > len)
166
+ # len = curlen;
167
+ # }
168
+ #
169
+ # /* Get space for the result list. */
170
+ # if ((result = (PyObject *) PyList_New(len)) == NULL)
171
+ # goto Fail_2;
172
+ #
173
+ # /* Iterate over the sequences until all have stopped. */
174
+ # for (i = 0; ; ++i) {
175
+ # PyObject *alist, *item=NULL, *value;
176
+ # int numactive = 0;
177
+ #
178
+ # if (func == Py_None && n == 1)
179
+ # alist = NULL;
180
+ # else if ((alist = PyTuple_New(n)) == NULL)
181
+ # goto Fail_1;
182
+ #
183
+ # for (j = 0, sqp = seqs; j < n; ++j, ++sqp) {
184
+ # if (sqp->saw_StopIteration) {
185
+ # Py_INCREF(Py_None);
186
+ # item = Py_None;
187
+ # }
188
+ # else {
189
+ # item = PyIter_Next(sqp->it);
190
+ # if (item)
191
+ # ++numactive;
192
+ # else {
193
+ # if (PyErr_Occurred()) {
194
+ # Py_XDECREF(alist);
195
+ # goto Fail_1;
196
+ # }
197
+ # Py_INCREF(Py_None);
198
+ # item = Py_None;
199
+ # sqp->saw_StopIteration = 1;
200
+ # }
201
+ # }
202
+ # if (alist)
203
+ # PyTuple_SET_ITEM(alist, j, item);
204
+ # else
205
+ # break;
206
+ # }
207
+ #
208
+ # if (!alist)
209
+ # alist = item;
210
+ #
211
+ # if (numactive == 0) {
212
+ # Py_DECREF(alist);
213
+ # break;
214
+ # }
215
+ #
216
+ # if (func == Py_None)
217
+ # value = alist;
218
+ # else {
219
+ # value = PyEval_CallObject(func, alist);
220
+ # Py_DECREF(alist);
221
+ # if (value == NULL)
222
+ # goto Fail_1;
223
+ # }
224
+ # if (i >= len) {
225
+ # int status = PyList_Append(result, value);
226
+ # Py_DECREF(value);
227
+ # if (status < 0)
228
+ # goto Fail_1;
229
+ # }
230
+ # else if (PyList_SetItem(result, i, value) < 0)
231
+ # goto Fail_1;
232
+ # }
233
+ #
234
+ # if (i < len && PyList_SetSlice(result, i, len, NULL) < 0)
235
+ # goto Fail_1;
236
+ #
237
+ # goto Succeed;
238
+ #
239
+ # Fail_1:
240
+ # Py_DECREF(result);
241
+ # Fail_2:
242
+ # result = NULL;
243
+ # Succeed:
244
+ # assert(seqs);
245
+ # for (i = 0; i < n; ++i)
246
+ # Py_XDECREF(seqs[i].it);
247
+ # PyMem_DEL(seqs);
248
+ # return result;
249
+ # }
250
+
251
+ def oldrange(*args, **kwargs):
252
+ return list(builtins.range(*args, **kwargs))
253
+
254
+ def oldzip(*args, **kwargs):
255
+ return list(builtins.zip(*args, **kwargs))
256
+
257
+ filter = oldfilter
258
+ map = oldmap
259
+ range = oldrange
260
+ from functools import reduce
261
+ zip = oldzip
262
+ __all__ = ['filter', 'map', 'range', 'reduce', 'zip']
263
+
264
+ else:
265
+ import __builtin__
266
+ # Python 2-builtin ranges produce lists
267
+ filter = __builtin__.filter
268
+ map = __builtin__.map
269
+ range = __builtin__.range
270
+ reduce = __builtin__.reduce
271
+ zip = __builtin__.zip
272
+ __all__ = []
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/translation/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (11.2 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/types/__init__.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Forward-ports of types from Python 2 for use with Python 3:
3
+
4
+ - ``basestring``: equivalent to ``(str, bytes)`` in ``isinstance`` checks
5
+ - ``dict``: with list-producing .keys() etc. methods
6
+ - ``str``: bytes-like, but iterating over them doesn't product integers
7
+ - ``long``: alias of Py3 int with ``L`` suffix in the ``repr``
8
+ - ``unicode``: alias of Py3 str with ``u`` prefix in the ``repr``
9
+
10
+ """
11
+
12
+ from past import utils
13
+
14
+ if utils.PY2:
15
+ import __builtin__
16
+ basestring = __builtin__.basestring
17
+ dict = __builtin__.dict
18
+ str = __builtin__.str
19
+ long = __builtin__.long
20
+ unicode = __builtin__.unicode
21
+ __all__ = []
22
+ else:
23
+ from .basestring import basestring
24
+ from .olddict import olddict
25
+ from .oldstr import oldstr
26
+ long = int
27
+ unicode = str
28
+ # from .unicode import unicode
29
+ __all__ = ['basestring', 'olddict', 'oldstr', 'long', 'unicode']
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/types/olddict.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ A dict subclass for Python 3 that behaves like Python 2's dict
3
+
4
+ Example use:
5
+
6
+ >>> from past.builtins import dict
7
+ >>> d1 = dict() # instead of {} for an empty dict
8
+ >>> d2 = dict(key1='value1', key2='value2')
9
+
10
+ The keys, values and items methods now return lists on Python 3.x and there are
11
+ methods for iterkeys, itervalues, iteritems, and viewkeys etc.
12
+
13
+ >>> for d in (d1, d2):
14
+ ... assert isinstance(d.keys(), list)
15
+ ... assert isinstance(d.values(), list)
16
+ ... assert isinstance(d.items(), list)
17
+ """
18
+
19
+ import sys
20
+
21
+ from past.utils import with_metaclass
22
+
23
+
24
+ _builtin_dict = dict
25
+ ver = sys.version_info[:2]
26
+
27
+
28
+ class BaseOldDict(type):
29
+ def __instancecheck__(cls, instance):
30
+ return isinstance(instance, _builtin_dict)
31
+
32
+
33
+ class olddict(with_metaclass(BaseOldDict, _builtin_dict)):
34
+ """
35
+ A backport of the Python 3 dict object to Py2
36
+ """
37
+ iterkeys = _builtin_dict.keys
38
+ viewkeys = _builtin_dict.keys
39
+
40
+ def keys(self):
41
+ return list(super(olddict, self).keys())
42
+
43
+ itervalues = _builtin_dict.values
44
+ viewvalues = _builtin_dict.values
45
+
46
+ def values(self):
47
+ return list(super(olddict, self).values())
48
+
49
+ iteritems = _builtin_dict.items
50
+ viewitems = _builtin_dict.items
51
+
52
+ def items(self):
53
+ return list(super(olddict, self).items())
54
+
55
+ def has_key(self, k):
56
+ """
57
+ D.has_key(k) -> True if D has a key k, else False
58
+ """
59
+ return k in self
60
+
61
+ # def __new__(cls, *args, **kwargs):
62
+ # """
63
+ # dict() -> new empty dictionary
64
+ # dict(mapping) -> new dictionary initialized from a mapping object's
65
+ # (key, value) pairs
66
+ # dict(iterable) -> new dictionary initialized as if via:
67
+ # d = {}
68
+ # for k, v in iterable:
69
+ # d[k] = v
70
+ # dict(**kwargs) -> new dictionary initialized with the name=value pairs
71
+ # in the keyword argument list. For example: dict(one=1, two=2)
72
+
73
+ # """
74
+ #
75
+ # if len(args) == 0:
76
+ # return super(olddict, cls).__new__(cls)
77
+ # # Was: elif isinstance(args[0], newbytes):
78
+ # # We use type() instead of the above because we're redefining
79
+ # # this to be True for all unicode string subclasses. Warning:
80
+ # # This may render newstr un-subclassable.
81
+ # elif type(args[0]) == olddict:
82
+ # return args[0]
83
+ # # elif isinstance(args[0], _builtin_dict):
84
+ # # value = args[0]
85
+ # else:
86
+ # value = args[0]
87
+ # return super(olddict, cls).__new__(cls, value)
88
+
89
+ def __native__(self):
90
+ """
91
+ Hook for the past.utils.native() function
92
+ """
93
+ return super(oldbytes, self)
94
+
95
+
96
+ __all__ = ['olddict']
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/types/oldstr.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Pure-Python implementation of a Python 2-like str object for Python 3.
3
+ """
4
+
5
+ from numbers import Integral
6
+
7
+ from past.utils import PY2, with_metaclass
8
+
9
+ if PY2:
10
+ from collections import Iterable
11
+ else:
12
+ from collections.abc import Iterable
13
+
14
+ _builtin_bytes = bytes
15
+
16
+
17
+ class BaseOldStr(type):
18
+ def __instancecheck__(cls, instance):
19
+ return isinstance(instance, _builtin_bytes)
20
+
21
+
22
+ def unescape(s):
23
+ """
24
+ Interprets strings with escape sequences
25
+
26
+ Example:
27
+ >>> s = unescape(r'abc\\def') # i.e. 'abc\\\\def'
28
+ >>> print(s)
29
+ 'abc\def'
30
+ >>> s2 = unescape('abc\\ndef')
31
+ >>> len(s2)
32
+ 8
33
+ >>> print(s2)
34
+ abc
35
+ def
36
+ """
37
+ return s.encode().decode('unicode_escape')
38
+
39
+
40
+ class oldstr(with_metaclass(BaseOldStr, _builtin_bytes)):
41
+ """
42
+ A forward port of the Python 2 8-bit string object to Py3
43
+ """
44
+ # Python 2 strings have no __iter__ method:
45
+ @property
46
+ def __iter__(self):
47
+ raise AttributeError
48
+
49
+ def __dir__(self):
50
+ return [thing for thing in dir(_builtin_bytes) if thing != '__iter__']
51
+
52
+ # def __new__(cls, *args, **kwargs):
53
+ # """
54
+ # From the Py3 bytes docstring:
55
+
56
+ # bytes(iterable_of_ints) -> bytes
57
+ # bytes(string, encoding[, errors]) -> bytes
58
+ # bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer
59
+ # bytes(int) -> bytes object of size given by the parameter initialized with null bytes
60
+ # bytes() -> empty bytes object
61
+ #
62
+ # Construct an immutable array of bytes from:
63
+ # - an iterable yielding integers in range(256)
64
+ # - a text string encoded using the specified encoding
65
+ # - any object implementing the buffer API.
66
+ # - an integer
67
+ # """
68
+ #
69
+ # if len(args) == 0:
70
+ # return super(newbytes, cls).__new__(cls)
71
+ # # Was: elif isinstance(args[0], newbytes):
72
+ # # We use type() instead of the above because we're redefining
73
+ # # this to be True for all unicode string subclasses. Warning:
74
+ # # This may render newstr un-subclassable.
75
+ # elif type(args[0]) == newbytes:
76
+ # return args[0]
77
+ # elif isinstance(args[0], _builtin_bytes):
78
+ # value = args[0]
79
+ # elif isinstance(args[0], unicode):
80
+ # if 'encoding' not in kwargs:
81
+ # raise TypeError('unicode string argument without an encoding')
82
+ # ###
83
+ # # Was: value = args[0].encode(**kwargs)
84
+ # # Python 2.6 string encode() method doesn't take kwargs:
85
+ # # Use this instead:
86
+ # newargs = [kwargs['encoding']]
87
+ # if 'errors' in kwargs:
88
+ # newargs.append(kwargs['errors'])
89
+ # value = args[0].encode(*newargs)
90
+ # ###
91
+ # elif isinstance(args[0], Iterable):
92
+ # if len(args[0]) == 0:
93
+ # # What is this?
94
+ # raise ValueError('unknown argument type')
95
+ # elif len(args[0]) > 0 and isinstance(args[0][0], Integral):
96
+ # # It's a list of integers
97
+ # value = b''.join([chr(x) for x in args[0]])
98
+ # else:
99
+ # raise ValueError('item cannot be interpreted as an integer')
100
+ # elif isinstance(args[0], Integral):
101
+ # if args[0] < 0:
102
+ # raise ValueError('negative count')
103
+ # value = b'\x00' * args[0]
104
+ # else:
105
+ # value = args[0]
106
+ # return super(newbytes, cls).__new__(cls, value)
107
+
108
+ def __repr__(self):
109
+ s = super(oldstr, self).__repr__() # e.g. b'abc' on Py3, b'abc' on Py3
110
+ return s[1:]
111
+
112
+ def __str__(self):
113
+ s = super(oldstr, self).__str__() # e.g. "b'abc'" or "b'abc\\ndef'
114
+ # TODO: fix this:
115
+ assert s[:2] == "b'" and s[-1] == "'"
116
+ return unescape(s[2:-1]) # e.g. 'abc' or 'abc\ndef'
117
+
118
+ def __getitem__(self, y):
119
+ if isinstance(y, Integral):
120
+ return super(oldstr, self).__getitem__(slice(y, y+1))
121
+ else:
122
+ return super(oldstr, self).__getitem__(y)
123
+
124
+ def __getslice__(self, *args):
125
+ return self.__getitem__(slice(*args))
126
+
127
+ def __contains__(self, key):
128
+ if isinstance(key, int):
129
+ return False
130
+
131
+ def __native__(self):
132
+ return bytes(self)
133
+
134
+
135
+ __all__ = ['oldstr']
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/past/utils/__init__.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Various non-built-in utility functions and definitions for Py2
3
+ compatibility in Py3.
4
+
5
+ For example:
6
+
7
+ >>> # The old_div() function behaves like Python 2's / operator
8
+ >>> # without "from __future__ import division"
9
+ >>> from past.utils import old_div
10
+ >>> old_div(3, 2) # like 3/2 in Py2
11
+ 0
12
+ >>> old_div(3, 2.0) # like 3/2.0 in Py2
13
+ 1.5
14
+ """
15
+
16
+ import sys
17
+ import numbers
18
+
19
+ PY3 = sys.version_info[0] >= 3
20
+ PY2 = sys.version_info[0] == 2
21
+ PYPY = hasattr(sys, 'pypy_translation_info')
22
+
23
+
24
+ def with_metaclass(meta, *bases):
25
+ """
26
+ Function from jinja2/_compat.py. License: BSD.
27
+
28
+ Use it like this::
29
+
30
+ class BaseForm(object):
31
+ pass
32
+
33
+ class FormType(type):
34
+ pass
35
+
36
+ class Form(with_metaclass(FormType, BaseForm)):
37
+ pass
38
+
39
+ This requires a bit of explanation: the basic idea is to make a
40
+ dummy metaclass for one level of class instantiation that replaces
41
+ itself with the actual metaclass. Because of internal type checks
42
+ we also need to make sure that we downgrade the custom metaclass
43
+ for one level to something closer to type (that's why __call__ and
44
+ __init__ comes back from type etc.).
45
+
46
+ This has the advantage over six.with_metaclass of not introducing
47
+ dummy classes into the final MRO.
48
+ """
49
+ class metaclass(meta):
50
+ __call__ = type.__call__
51
+ __init__ = type.__init__
52
+ def __new__(cls, name, this_bases, d):
53
+ if this_bases is None:
54
+ return type.__new__(cls, name, (), d)
55
+ return meta(name, bases, d)
56
+ return metaclass('temporary_class', None, {})
57
+
58
+
59
+ def native(obj):
60
+ """
61
+ On Py2, this is a no-op: native(obj) -> obj
62
+
63
+ On Py3, returns the corresponding native Py3 types that are
64
+ superclasses for forward-ported objects from Py2:
65
+
66
+ >>> from past.builtins import str, dict
67
+
68
+ >>> native(str(b'ABC')) # Output on Py3 follows. On Py2, output is 'ABC'
69
+ b'ABC'
70
+ >>> type(native(str(b'ABC')))
71
+ bytes
72
+
73
+ Existing native types on Py3 will be returned unchanged:
74
+
75
+ >>> type(native(b'ABC'))
76
+ bytes
77
+ """
78
+ if hasattr(obj, '__native__'):
79
+ return obj.__native__()
80
+ else:
81
+ return obj
82
+
83
+
84
+ # An alias for future.utils.old_div():
85
+ def old_div(a, b):
86
+ """
87
+ Equivalent to ``a / b`` on Python 2 without ``from __future__ import
88
+ division``.
89
+
90
+ TODO: generalize this to other objects (like arrays etc.)
91
+ """
92
+ if isinstance(a, numbers.Integral) and isinstance(b, numbers.Integral):
93
+ return a // b
94
+ else:
95
+ return a / b
96
+
97
+ __all__ = ['PY3', 'PY2', 'PYPY', 'with_metaclass', 'native', 'old_div']
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (1.46 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/_load_gpu_decoder.cpython-38.pyc ADDED
Binary file (335 Bytes). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/_video_opt.cpython-38.pyc ADDED
Binary file (15.5 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/image.cpython-38.pyc ADDED
Binary file (9.53 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/video.cpython-38.pyc ADDED
Binary file (11.6 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/__pycache__/video_reader.cpython-38.pyc ADDED
Binary file (7.08 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/_video_opt.py ADDED
@@ -0,0 +1,505 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import warnings
3
+ from fractions import Fraction
4
+ from typing import List, Tuple, Dict, Optional, Union
5
+
6
+ import torch
7
+
8
+ from ..extension import _load_library
9
+
10
+
11
+ try:
12
+ _load_library("video_reader")
13
+ _HAS_VIDEO_OPT = True
14
+ except (ImportError, OSError):
15
+ _HAS_VIDEO_OPT = False
16
+
17
+ default_timebase = Fraction(0, 1)
18
+
19
+
20
+ # simple class for torch scripting
21
+ # the complex Fraction class from fractions module is not scriptable
22
+ class Timebase:
23
+ __annotations__ = {"numerator": int, "denominator": int}
24
+ __slots__ = ["numerator", "denominator"]
25
+
26
+ def __init__(
27
+ self,
28
+ numerator: int,
29
+ denominator: int,
30
+ ) -> None:
31
+ self.numerator = numerator
32
+ self.denominator = denominator
33
+
34
+
35
+ class VideoMetaData:
36
+ __annotations__ = {
37
+ "has_video": bool,
38
+ "video_timebase": Timebase,
39
+ "video_duration": float,
40
+ "video_fps": float,
41
+ "has_audio": bool,
42
+ "audio_timebase": Timebase,
43
+ "audio_duration": float,
44
+ "audio_sample_rate": float,
45
+ }
46
+ __slots__ = [
47
+ "has_video",
48
+ "video_timebase",
49
+ "video_duration",
50
+ "video_fps",
51
+ "has_audio",
52
+ "audio_timebase",
53
+ "audio_duration",
54
+ "audio_sample_rate",
55
+ ]
56
+
57
+ def __init__(self) -> None:
58
+ self.has_video = False
59
+ self.video_timebase = Timebase(0, 1)
60
+ self.video_duration = 0.0
61
+ self.video_fps = 0.0
62
+ self.has_audio = False
63
+ self.audio_timebase = Timebase(0, 1)
64
+ self.audio_duration = 0.0
65
+ self.audio_sample_rate = 0.0
66
+
67
+
68
+ def _validate_pts(pts_range: Tuple[int, int]) -> None:
69
+
70
+ if pts_range[0] > pts_range[1] > 0:
71
+ raise ValueError(
72
+ f"Start pts should not be smaller than end pts, got start pts: {pts_range[0]} and end pts: {pts_range[1]}"
73
+ )
74
+
75
+
76
+ def _fill_info(
77
+ vtimebase: torch.Tensor,
78
+ vfps: torch.Tensor,
79
+ vduration: torch.Tensor,
80
+ atimebase: torch.Tensor,
81
+ asample_rate: torch.Tensor,
82
+ aduration: torch.Tensor,
83
+ ) -> VideoMetaData:
84
+ """
85
+ Build update VideoMetaData struct with info about the video
86
+ """
87
+ meta = VideoMetaData()
88
+ if vtimebase.numel() > 0:
89
+ meta.video_timebase = Timebase(int(vtimebase[0].item()), int(vtimebase[1].item()))
90
+ timebase = vtimebase[0].item() / float(vtimebase[1].item())
91
+ if vduration.numel() > 0:
92
+ meta.has_video = True
93
+ meta.video_duration = float(vduration.item()) * timebase
94
+ if vfps.numel() > 0:
95
+ meta.video_fps = float(vfps.item())
96
+ if atimebase.numel() > 0:
97
+ meta.audio_timebase = Timebase(int(atimebase[0].item()), int(atimebase[1].item()))
98
+ timebase = atimebase[0].item() / float(atimebase[1].item())
99
+ if aduration.numel() > 0:
100
+ meta.has_audio = True
101
+ meta.audio_duration = float(aduration.item()) * timebase
102
+ if asample_rate.numel() > 0:
103
+ meta.audio_sample_rate = float(asample_rate.item())
104
+
105
+ return meta
106
+
107
+
108
+ def _align_audio_frames(
109
+ aframes: torch.Tensor, aframe_pts: torch.Tensor, audio_pts_range: Tuple[int, int]
110
+ ) -> torch.Tensor:
111
+ start, end = aframe_pts[0], aframe_pts[-1]
112
+ num_samples = aframes.size(0)
113
+ step_per_aframe = float(end - start + 1) / float(num_samples)
114
+ s_idx = 0
115
+ e_idx = num_samples
116
+ if start < audio_pts_range[0]:
117
+ s_idx = int((audio_pts_range[0] - start) / step_per_aframe)
118
+ if audio_pts_range[1] != -1 and end > audio_pts_range[1]:
119
+ e_idx = int((audio_pts_range[1] - end) / step_per_aframe)
120
+ return aframes[s_idx:e_idx, :]
121
+
122
+
123
+ def _read_video_from_file(
124
+ filename: str,
125
+ seek_frame_margin: float = 0.25,
126
+ read_video_stream: bool = True,
127
+ video_width: int = 0,
128
+ video_height: int = 0,
129
+ video_min_dimension: int = 0,
130
+ video_max_dimension: int = 0,
131
+ video_pts_range: Tuple[int, int] = (0, -1),
132
+ video_timebase: Fraction = default_timebase,
133
+ read_audio_stream: bool = True,
134
+ audio_samples: int = 0,
135
+ audio_channels: int = 0,
136
+ audio_pts_range: Tuple[int, int] = (0, -1),
137
+ audio_timebase: Fraction = default_timebase,
138
+ ) -> Tuple[torch.Tensor, torch.Tensor, VideoMetaData]:
139
+ """
140
+ Reads a video from a file, returning both the video frames as well as
141
+ the audio frames
142
+
143
+ Args:
144
+ filename (str): path to the video file
145
+ seek_frame_margin (double, optional): seeking frame in the stream is imprecise. Thus,
146
+ when video_start_pts is specified, we seek the pts earlier by seek_frame_margin seconds
147
+ read_video_stream (int, optional): whether read video stream. If yes, set to 1. Otherwise, 0
148
+ video_width/video_height/video_min_dimension/video_max_dimension (int): together decide
149
+ the size of decoded frames:
150
+
151
+ - When video_width = 0, video_height = 0, video_min_dimension = 0,
152
+ and video_max_dimension = 0, keep the original frame resolution
153
+ - When video_width = 0, video_height = 0, video_min_dimension != 0,
154
+ and video_max_dimension = 0, keep the aspect ratio and resize the
155
+ frame so that shorter edge size is video_min_dimension
156
+ - When video_width = 0, video_height = 0, video_min_dimension = 0,
157
+ and video_max_dimension != 0, keep the aspect ratio and resize
158
+ the frame so that longer edge size is video_max_dimension
159
+ - When video_width = 0, video_height = 0, video_min_dimension != 0,
160
+ and video_max_dimension != 0, resize the frame so that shorter
161
+ edge size is video_min_dimension, and longer edge size is
162
+ video_max_dimension. The aspect ratio may not be preserved
163
+ - When video_width = 0, video_height != 0, video_min_dimension = 0,
164
+ and video_max_dimension = 0, keep the aspect ratio and resize
165
+ the frame so that frame video_height is $video_height
166
+ - When video_width != 0, video_height == 0, video_min_dimension = 0,
167
+ and video_max_dimension = 0, keep the aspect ratio and resize
168
+ the frame so that frame video_width is $video_width
169
+ - When video_width != 0, video_height != 0, video_min_dimension = 0,
170
+ and video_max_dimension = 0, resize the frame so that frame
171
+ video_width and video_height are set to $video_width and
172
+ $video_height, respectively
173
+ video_pts_range (list(int), optional): the start and end presentation timestamp of video stream
174
+ video_timebase (Fraction, optional): a Fraction rational number which denotes timebase in video stream
175
+ read_audio_stream (int, optional): whether read audio stream. If yes, set to 1. Otherwise, 0
176
+ audio_samples (int, optional): audio sampling rate
177
+ audio_channels (int optional): audio channels
178
+ audio_pts_range (list(int), optional): the start and end presentation timestamp of audio stream
179
+ audio_timebase (Fraction, optional): a Fraction rational number which denotes time base in audio stream
180
+
181
+ Returns
182
+ vframes (Tensor[T, H, W, C]): the `T` video frames
183
+ aframes (Tensor[L, K]): the audio frames, where `L` is the number of points and
184
+ `K` is the number of audio_channels
185
+ info (Dict): metadata for the video and audio. Can contain the fields video_fps (float)
186
+ and audio_fps (int)
187
+ """
188
+ _validate_pts(video_pts_range)
189
+ _validate_pts(audio_pts_range)
190
+
191
+ result = torch.ops.video_reader.read_video_from_file(
192
+ filename,
193
+ seek_frame_margin,
194
+ 0, # getPtsOnly
195
+ read_video_stream,
196
+ video_width,
197
+ video_height,
198
+ video_min_dimension,
199
+ video_max_dimension,
200
+ video_pts_range[0],
201
+ video_pts_range[1],
202
+ video_timebase.numerator,
203
+ video_timebase.denominator,
204
+ read_audio_stream,
205
+ audio_samples,
206
+ audio_channels,
207
+ audio_pts_range[0],
208
+ audio_pts_range[1],
209
+ audio_timebase.numerator,
210
+ audio_timebase.denominator,
211
+ )
212
+ vframes, _vframe_pts, vtimebase, vfps, vduration, aframes, aframe_pts, atimebase, asample_rate, aduration = result
213
+ info = _fill_info(vtimebase, vfps, vduration, atimebase, asample_rate, aduration)
214
+ if aframes.numel() > 0:
215
+ # when audio stream is found
216
+ aframes = _align_audio_frames(aframes, aframe_pts, audio_pts_range)
217
+ return vframes, aframes, info
218
+
219
+
220
+ def _read_video_timestamps_from_file(filename: str) -> Tuple[List[int], List[int], VideoMetaData]:
221
+ """
222
+ Decode all video- and audio frames in the video. Only pts
223
+ (presentation timestamp) is returned. The actual frame pixel data is not
224
+ copied. Thus, it is much faster than read_video(...)
225
+ """
226
+ result = torch.ops.video_reader.read_video_from_file(
227
+ filename,
228
+ 0, # seek_frame_margin
229
+ 1, # getPtsOnly
230
+ 1, # read_video_stream
231
+ 0, # video_width
232
+ 0, # video_height
233
+ 0, # video_min_dimension
234
+ 0, # video_max_dimension
235
+ 0, # video_start_pts
236
+ -1, # video_end_pts
237
+ 0, # video_timebase_num
238
+ 1, # video_timebase_den
239
+ 1, # read_audio_stream
240
+ 0, # audio_samples
241
+ 0, # audio_channels
242
+ 0, # audio_start_pts
243
+ -1, # audio_end_pts
244
+ 0, # audio_timebase_num
245
+ 1, # audio_timebase_den
246
+ )
247
+ _vframes, vframe_pts, vtimebase, vfps, vduration, _aframes, aframe_pts, atimebase, asample_rate, aduration = result
248
+ info = _fill_info(vtimebase, vfps, vduration, atimebase, asample_rate, aduration)
249
+
250
+ vframe_pts = vframe_pts.numpy().tolist()
251
+ aframe_pts = aframe_pts.numpy().tolist()
252
+ return vframe_pts, aframe_pts, info
253
+
254
+
255
+ def _probe_video_from_file(filename: str) -> VideoMetaData:
256
+ """
257
+ Probe a video file and return VideoMetaData with info about the video
258
+ """
259
+ result = torch.ops.video_reader.probe_video_from_file(filename)
260
+ vtimebase, vfps, vduration, atimebase, asample_rate, aduration = result
261
+ info = _fill_info(vtimebase, vfps, vduration, atimebase, asample_rate, aduration)
262
+ return info
263
+
264
+
265
+ def _read_video_from_memory(
266
+ video_data: torch.Tensor,
267
+ seek_frame_margin: float = 0.25,
268
+ read_video_stream: int = 1,
269
+ video_width: int = 0,
270
+ video_height: int = 0,
271
+ video_min_dimension: int = 0,
272
+ video_max_dimension: int = 0,
273
+ video_pts_range: Tuple[int, int] = (0, -1),
274
+ video_timebase_numerator: int = 0,
275
+ video_timebase_denominator: int = 1,
276
+ read_audio_stream: int = 1,
277
+ audio_samples: int = 0,
278
+ audio_channels: int = 0,
279
+ audio_pts_range: Tuple[int, int] = (0, -1),
280
+ audio_timebase_numerator: int = 0,
281
+ audio_timebase_denominator: int = 1,
282
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
283
+ """
284
+ Reads a video from memory, returning both the video frames as well as
285
+ the audio frames
286
+ This function is torchscriptable.
287
+
288
+ Args:
289
+ video_data (data type could be 1) torch.Tensor, dtype=torch.int8 or 2) python bytes):
290
+ compressed video content stored in either 1) torch.Tensor 2) python bytes
291
+ seek_frame_margin (double, optional): seeking frame in the stream is imprecise.
292
+ Thus, when video_start_pts is specified, we seek the pts earlier by seek_frame_margin seconds
293
+ read_video_stream (int, optional): whether read video stream. If yes, set to 1. Otherwise, 0
294
+ video_width/video_height/video_min_dimension/video_max_dimension (int): together decide
295
+ the size of decoded frames:
296
+
297
+ - When video_width = 0, video_height = 0, video_min_dimension = 0,
298
+ and video_max_dimension = 0, keep the original frame resolution
299
+ - When video_width = 0, video_height = 0, video_min_dimension != 0,
300
+ and video_max_dimension = 0, keep the aspect ratio and resize the
301
+ frame so that shorter edge size is video_min_dimension
302
+ - When video_width = 0, video_height = 0, video_min_dimension = 0,
303
+ and video_max_dimension != 0, keep the aspect ratio and resize
304
+ the frame so that longer edge size is video_max_dimension
305
+ - When video_width = 0, video_height = 0, video_min_dimension != 0,
306
+ and video_max_dimension != 0, resize the frame so that shorter
307
+ edge size is video_min_dimension, and longer edge size is
308
+ video_max_dimension. The aspect ratio may not be preserved
309
+ - When video_width = 0, video_height != 0, video_min_dimension = 0,
310
+ and video_max_dimension = 0, keep the aspect ratio and resize
311
+ the frame so that frame video_height is $video_height
312
+ - When video_width != 0, video_height == 0, video_min_dimension = 0,
313
+ and video_max_dimension = 0, keep the aspect ratio and resize
314
+ the frame so that frame video_width is $video_width
315
+ - When video_width != 0, video_height != 0, video_min_dimension = 0,
316
+ and video_max_dimension = 0, resize the frame so that frame
317
+ video_width and video_height are set to $video_width and
318
+ $video_height, respectively
319
+ video_pts_range (list(int), optional): the start and end presentation timestamp of video stream
320
+ video_timebase_numerator / video_timebase_denominator (float, optional): a rational
321
+ number which denotes timebase in video stream
322
+ read_audio_stream (int, optional): whether read audio stream. If yes, set to 1. Otherwise, 0
323
+ audio_samples (int, optional): audio sampling rate
324
+ audio_channels (int optional): audio audio_channels
325
+ audio_pts_range (list(int), optional): the start and end presentation timestamp of audio stream
326
+ audio_timebase_numerator / audio_timebase_denominator (float, optional):
327
+ a rational number which denotes time base in audio stream
328
+
329
+ Returns:
330
+ vframes (Tensor[T, H, W, C]): the `T` video frames
331
+ aframes (Tensor[L, K]): the audio frames, where `L` is the number of points and
332
+ `K` is the number of channels
333
+ """
334
+
335
+ _validate_pts(video_pts_range)
336
+ _validate_pts(audio_pts_range)
337
+
338
+ if not isinstance(video_data, torch.Tensor):
339
+ video_data = torch.frombuffer(video_data, dtype=torch.uint8)
340
+
341
+ result = torch.ops.video_reader.read_video_from_memory(
342
+ video_data,
343
+ seek_frame_margin,
344
+ 0, # getPtsOnly
345
+ read_video_stream,
346
+ video_width,
347
+ video_height,
348
+ video_min_dimension,
349
+ video_max_dimension,
350
+ video_pts_range[0],
351
+ video_pts_range[1],
352
+ video_timebase_numerator,
353
+ video_timebase_denominator,
354
+ read_audio_stream,
355
+ audio_samples,
356
+ audio_channels,
357
+ audio_pts_range[0],
358
+ audio_pts_range[1],
359
+ audio_timebase_numerator,
360
+ audio_timebase_denominator,
361
+ )
362
+
363
+ vframes, _vframe_pts, vtimebase, vfps, vduration, aframes, aframe_pts, atimebase, asample_rate, aduration = result
364
+
365
+ if aframes.numel() > 0:
366
+ # when audio stream is found
367
+ aframes = _align_audio_frames(aframes, aframe_pts, audio_pts_range)
368
+
369
+ return vframes, aframes
370
+
371
+
372
+ def _read_video_timestamps_from_memory(
373
+ video_data: torch.Tensor,
374
+ ) -> Tuple[List[int], List[int], VideoMetaData]:
375
+ """
376
+ Decode all frames in the video. Only pts (presentation timestamp) is returned.
377
+ The actual frame pixel data is not copied. Thus, read_video_timestamps(...)
378
+ is much faster than read_video(...)
379
+ """
380
+ if not isinstance(video_data, torch.Tensor):
381
+ video_data = torch.frombuffer(video_data, dtype=torch.uint8)
382
+ result = torch.ops.video_reader.read_video_from_memory(
383
+ video_data,
384
+ 0, # seek_frame_margin
385
+ 1, # getPtsOnly
386
+ 1, # read_video_stream
387
+ 0, # video_width
388
+ 0, # video_height
389
+ 0, # video_min_dimension
390
+ 0, # video_max_dimension
391
+ 0, # video_start_pts
392
+ -1, # video_end_pts
393
+ 0, # video_timebase_num
394
+ 1, # video_timebase_den
395
+ 1, # read_audio_stream
396
+ 0, # audio_samples
397
+ 0, # audio_channels
398
+ 0, # audio_start_pts
399
+ -1, # audio_end_pts
400
+ 0, # audio_timebase_num
401
+ 1, # audio_timebase_den
402
+ )
403
+ _vframes, vframe_pts, vtimebase, vfps, vduration, _aframes, aframe_pts, atimebase, asample_rate, aduration = result
404
+ info = _fill_info(vtimebase, vfps, vduration, atimebase, asample_rate, aduration)
405
+
406
+ vframe_pts = vframe_pts.numpy().tolist()
407
+ aframe_pts = aframe_pts.numpy().tolist()
408
+ return vframe_pts, aframe_pts, info
409
+
410
+
411
+ def _probe_video_from_memory(
412
+ video_data: torch.Tensor,
413
+ ) -> VideoMetaData:
414
+ """
415
+ Probe a video in memory and return VideoMetaData with info about the video
416
+ This function is torchscriptable
417
+ """
418
+ if not isinstance(video_data, torch.Tensor):
419
+ video_data = torch.frombuffer(video_data, dtype=torch.uint8)
420
+ result = torch.ops.video_reader.probe_video_from_memory(video_data)
421
+ vtimebase, vfps, vduration, atimebase, asample_rate, aduration = result
422
+ info = _fill_info(vtimebase, vfps, vduration, atimebase, asample_rate, aduration)
423
+ return info
424
+
425
+
426
+ def _read_video(
427
+ filename: str,
428
+ start_pts: Union[float, Fraction] = 0,
429
+ end_pts: Optional[Union[float, Fraction]] = None,
430
+ pts_unit: str = "pts",
431
+ ) -> Tuple[torch.Tensor, torch.Tensor, Dict[str, float]]:
432
+ if end_pts is None:
433
+ end_pts = float("inf")
434
+
435
+ if pts_unit == "pts":
436
+ warnings.warn(
437
+ "The pts_unit 'pts' gives wrong results and will be removed in a "
438
+ + "follow-up version. Please use pts_unit 'sec'."
439
+ )
440
+
441
+ info = _probe_video_from_file(filename)
442
+
443
+ has_video = info.has_video
444
+ has_audio = info.has_audio
445
+
446
+ def get_pts(time_base):
447
+ start_offset = start_pts
448
+ end_offset = end_pts
449
+ if pts_unit == "sec":
450
+ start_offset = int(math.floor(start_pts * (1 / time_base)))
451
+ if end_offset != float("inf"):
452
+ end_offset = int(math.ceil(end_pts * (1 / time_base)))
453
+ if end_offset == float("inf"):
454
+ end_offset = -1
455
+ return start_offset, end_offset
456
+
457
+ video_pts_range = (0, -1)
458
+ video_timebase = default_timebase
459
+ if has_video:
460
+ video_timebase = Fraction(info.video_timebase.numerator, info.video_timebase.denominator)
461
+ video_pts_range = get_pts(video_timebase)
462
+
463
+ audio_pts_range = (0, -1)
464
+ audio_timebase = default_timebase
465
+ if has_audio:
466
+ audio_timebase = Fraction(info.audio_timebase.numerator, info.audio_timebase.denominator)
467
+ audio_pts_range = get_pts(audio_timebase)
468
+
469
+ vframes, aframes, info = _read_video_from_file(
470
+ filename,
471
+ read_video_stream=True,
472
+ video_pts_range=video_pts_range,
473
+ video_timebase=video_timebase,
474
+ read_audio_stream=True,
475
+ audio_pts_range=audio_pts_range,
476
+ audio_timebase=audio_timebase,
477
+ )
478
+ _info = {}
479
+ if has_video:
480
+ _info["video_fps"] = info.video_fps
481
+ if has_audio:
482
+ _info["audio_fps"] = info.audio_sample_rate
483
+
484
+ return vframes, aframes, _info
485
+
486
+
487
+ def _read_video_timestamps(
488
+ filename: str, pts_unit: str = "pts"
489
+ ) -> Tuple[Union[List[int], List[Fraction]], Optional[float]]:
490
+ if pts_unit == "pts":
491
+ warnings.warn(
492
+ "The pts_unit 'pts' gives wrong results and will be removed in a "
493
+ + "follow-up version. Please use pts_unit 'sec'."
494
+ )
495
+
496
+ pts: Union[List[int], List[Fraction]]
497
+ pts, _, info = _read_video_timestamps_from_file(filename)
498
+
499
+ if pts_unit == "sec":
500
+ video_time_base = Fraction(info.video_timebase.numerator, info.video_timebase.denominator)
501
+ pts = [x * video_time_base for x in pts]
502
+
503
+ video_fps = info.video_fps if info.has_video else None
504
+
505
+ return pts, video_fps
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/image.py ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from enum import Enum
2
+ from warnings import warn
3
+
4
+ import torch
5
+
6
+ from ..extension import _load_library
7
+ from ..utils import _log_api_usage_once
8
+
9
+
10
+ try:
11
+ _load_library("image")
12
+ except (ImportError, OSError) as e:
13
+ warn(f"Failed to load image Python extension: {e}")
14
+
15
+
16
+ class ImageReadMode(Enum):
17
+ """
18
+ Support for various modes while reading images.
19
+
20
+ Use ``ImageReadMode.UNCHANGED`` for loading the image as-is,
21
+ ``ImageReadMode.GRAY`` for converting to grayscale,
22
+ ``ImageReadMode.GRAY_ALPHA`` for grayscale with transparency,
23
+ ``ImageReadMode.RGB`` for RGB and ``ImageReadMode.RGB_ALPHA`` for
24
+ RGB with transparency.
25
+ """
26
+
27
+ UNCHANGED = 0
28
+ GRAY = 1
29
+ GRAY_ALPHA = 2
30
+ RGB = 3
31
+ RGB_ALPHA = 4
32
+
33
+
34
+ def read_file(path: str) -> torch.Tensor:
35
+ """
36
+ Reads and outputs the bytes contents of a file as a uint8 Tensor
37
+ with one dimension.
38
+
39
+ Args:
40
+ path (str): the path to the file to be read
41
+
42
+ Returns:
43
+ data (Tensor)
44
+ """
45
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
46
+ _log_api_usage_once(read_file)
47
+ data = torch.ops.image.read_file(path)
48
+ return data
49
+
50
+
51
+ def write_file(filename: str, data: torch.Tensor) -> None:
52
+ """
53
+ Writes the contents of a uint8 tensor with one dimension to a
54
+ file.
55
+
56
+ Args:
57
+ filename (str): the path to the file to be written
58
+ data (Tensor): the contents to be written to the output file
59
+ """
60
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
61
+ _log_api_usage_once(write_file)
62
+ torch.ops.image.write_file(filename, data)
63
+
64
+
65
+ def decode_png(input: torch.Tensor, mode: ImageReadMode = ImageReadMode.UNCHANGED) -> torch.Tensor:
66
+ """
67
+ Decodes a PNG image into a 3 dimensional RGB or grayscale Tensor.
68
+ Optionally converts the image to the desired format.
69
+ The values of the output tensor are uint8 in [0, 255].
70
+
71
+ Args:
72
+ input (Tensor[1]): a one dimensional uint8 tensor containing
73
+ the raw bytes of the PNG image.
74
+ mode (ImageReadMode): the read mode used for optionally
75
+ converting the image. Default: ``ImageReadMode.UNCHANGED``.
76
+ See `ImageReadMode` class for more information on various
77
+ available modes.
78
+
79
+ Returns:
80
+ output (Tensor[image_channels, image_height, image_width])
81
+ """
82
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
83
+ _log_api_usage_once(decode_png)
84
+ output = torch.ops.image.decode_png(input, mode.value, False)
85
+ return output
86
+
87
+
88
+ def encode_png(input: torch.Tensor, compression_level: int = 6) -> torch.Tensor:
89
+ """
90
+ Takes an input tensor in CHW layout and returns a buffer with the contents
91
+ of its corresponding PNG file.
92
+
93
+ Args:
94
+ input (Tensor[channels, image_height, image_width]): int8 image tensor of
95
+ ``c`` channels, where ``c`` must 3 or 1.
96
+ compression_level (int): Compression factor for the resulting file, it must be a number
97
+ between 0 and 9. Default: 6
98
+
99
+ Returns:
100
+ Tensor[1]: A one dimensional int8 tensor that contains the raw bytes of the
101
+ PNG file.
102
+ """
103
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
104
+ _log_api_usage_once(encode_png)
105
+ output = torch.ops.image.encode_png(input, compression_level)
106
+ return output
107
+
108
+
109
+ def write_png(input: torch.Tensor, filename: str, compression_level: int = 6):
110
+ """
111
+ Takes an input tensor in CHW layout (or HW in the case of grayscale images)
112
+ and saves it in a PNG file.
113
+
114
+ Args:
115
+ input (Tensor[channels, image_height, image_width]): int8 image tensor of
116
+ ``c`` channels, where ``c`` must be 1 or 3.
117
+ filename (str): Path to save the image.
118
+ compression_level (int): Compression factor for the resulting file, it must be a number
119
+ between 0 and 9. Default: 6
120
+ """
121
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
122
+ _log_api_usage_once(write_png)
123
+ output = encode_png(input, compression_level)
124
+ write_file(filename, output)
125
+
126
+
127
+ def decode_jpeg(
128
+ input: torch.Tensor, mode: ImageReadMode = ImageReadMode.UNCHANGED, device: str = "cpu"
129
+ ) -> torch.Tensor:
130
+ """
131
+ Decodes a JPEG image into a 3 dimensional RGB or grayscale Tensor.
132
+ Optionally converts the image to the desired format.
133
+ The values of the output tensor are uint8 between 0 and 255.
134
+
135
+ Args:
136
+ input (Tensor[1]): a one dimensional uint8 tensor containing
137
+ the raw bytes of the JPEG image. This tensor must be on CPU,
138
+ regardless of the ``device`` parameter.
139
+ mode (ImageReadMode): the read mode used for optionally
140
+ converting the image. Default: ``ImageReadMode.UNCHANGED``.
141
+ See ``ImageReadMode`` class for more information on various
142
+ available modes.
143
+ device (str or torch.device): The device on which the decoded image will
144
+ be stored. If a cuda device is specified, the image will be decoded
145
+ with `nvjpeg <https://developer.nvidia.com/nvjpeg>`_. This is only
146
+ supported for CUDA version >= 10.1
147
+
148
+ .. betastatus:: device parameter
149
+
150
+ .. warning::
151
+ There is a memory leak in the nvjpeg library for CUDA versions < 11.6.
152
+ Make sure to rely on CUDA 11.6 or above before using ``device="cuda"``.
153
+
154
+ Returns:
155
+ output (Tensor[image_channels, image_height, image_width])
156
+ """
157
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
158
+ _log_api_usage_once(decode_jpeg)
159
+ device = torch.device(device)
160
+ if device.type == "cuda":
161
+ output = torch.ops.image.decode_jpeg_cuda(input, mode.value, device)
162
+ else:
163
+ output = torch.ops.image.decode_jpeg(input, mode.value)
164
+ return output
165
+
166
+
167
+ def encode_jpeg(input: torch.Tensor, quality: int = 75) -> torch.Tensor:
168
+ """
169
+ Takes an input tensor in CHW layout and returns a buffer with the contents
170
+ of its corresponding JPEG file.
171
+
172
+ Args:
173
+ input (Tensor[channels, image_height, image_width])): int8 image tensor of
174
+ ``c`` channels, where ``c`` must be 1 or 3.
175
+ quality (int): Quality of the resulting JPEG file, it must be a number between
176
+ 1 and 100. Default: 75
177
+
178
+ Returns:
179
+ output (Tensor[1]): A one dimensional int8 tensor that contains the raw bytes of the
180
+ JPEG file.
181
+ """
182
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
183
+ _log_api_usage_once(encode_jpeg)
184
+ if quality < 1 or quality > 100:
185
+ raise ValueError("Image quality should be a positive number between 1 and 100")
186
+
187
+ output = torch.ops.image.encode_jpeg(input, quality)
188
+ return output
189
+
190
+
191
+ def write_jpeg(input: torch.Tensor, filename: str, quality: int = 75):
192
+ """
193
+ Takes an input tensor in CHW layout and saves it in a JPEG file.
194
+
195
+ Args:
196
+ input (Tensor[channels, image_height, image_width]): int8 image tensor of ``c``
197
+ channels, where ``c`` must be 1 or 3.
198
+ filename (str): Path to save the image.
199
+ quality (int): Quality of the resulting JPEG file, it must be a number
200
+ between 1 and 100. Default: 75
201
+ """
202
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
203
+ _log_api_usage_once(write_jpeg)
204
+ output = encode_jpeg(input, quality)
205
+ write_file(filename, output)
206
+
207
+
208
+ def decode_image(input: torch.Tensor, mode: ImageReadMode = ImageReadMode.UNCHANGED) -> torch.Tensor:
209
+ """
210
+ Detects whether an image is a JPEG or PNG and performs the appropriate
211
+ operation to decode the image into a 3 dimensional RGB or grayscale Tensor.
212
+
213
+ Optionally converts the image to the desired format.
214
+ The values of the output tensor are uint8 in [0, 255].
215
+
216
+ Args:
217
+ input (Tensor): a one dimensional uint8 tensor containing the raw bytes of the
218
+ PNG or JPEG image.
219
+ mode (ImageReadMode): the read mode used for optionally converting the image.
220
+ Default: ``ImageReadMode.UNCHANGED``.
221
+ See ``ImageReadMode`` class for more information on various
222
+ available modes.
223
+
224
+ Returns:
225
+ output (Tensor[image_channels, image_height, image_width])
226
+ """
227
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
228
+ _log_api_usage_once(decode_image)
229
+ output = torch.ops.image.decode_image(input, mode.value)
230
+ return output
231
+
232
+
233
+ def read_image(path: str, mode: ImageReadMode = ImageReadMode.UNCHANGED) -> torch.Tensor:
234
+ """
235
+ Reads a JPEG or PNG image into a 3 dimensional RGB or grayscale Tensor.
236
+ Optionally converts the image to the desired format.
237
+ The values of the output tensor are uint8 in [0, 255].
238
+
239
+ Args:
240
+ path (str): path of the JPEG or PNG image.
241
+ mode (ImageReadMode): the read mode used for optionally converting the image.
242
+ Default: ``ImageReadMode.UNCHANGED``.
243
+ See ``ImageReadMode`` class for more information on various
244
+ available modes.
245
+
246
+ Returns:
247
+ output (Tensor[image_channels, image_height, image_width])
248
+ """
249
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
250
+ _log_api_usage_once(read_image)
251
+ data = read_file(path)
252
+ return decode_image(data, mode)
253
+
254
+
255
+ def _read_png_16(path: str, mode: ImageReadMode = ImageReadMode.UNCHANGED) -> torch.Tensor:
256
+ data = read_file(path)
257
+ return torch.ops.image.decode_png(data, mode.value, True)
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/io/video.py ADDED
@@ -0,0 +1,415 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gc
2
+ import math
3
+ import os
4
+ import re
5
+ import warnings
6
+ from fractions import Fraction
7
+ from typing import Any, Dict, List, Optional, Tuple, Union
8
+
9
+ import numpy as np
10
+ import torch
11
+
12
+ from ..utils import _log_api_usage_once
13
+ from . import _video_opt
14
+
15
+
16
+ try:
17
+ import av
18
+
19
+ av.logging.set_level(av.logging.ERROR)
20
+ if not hasattr(av.video.frame.VideoFrame, "pict_type"):
21
+ av = ImportError(
22
+ """\
23
+ Your version of PyAV is too old for the necessary video operations in torchvision.
24
+ If you are on Python 3.5, you will have to build from source (the conda-forge
25
+ packages are not up-to-date). See
26
+ https://github.com/mikeboers/PyAV#installation for instructions on how to
27
+ install PyAV on your system.
28
+ """
29
+ )
30
+ except ImportError:
31
+ av = ImportError(
32
+ """\
33
+ PyAV is not installed, and is necessary for the video operations in torchvision.
34
+ See https://github.com/mikeboers/PyAV#installation for instructions on how to
35
+ install PyAV on your system.
36
+ """
37
+ )
38
+
39
+
40
+ def _check_av_available() -> None:
41
+ if isinstance(av, Exception):
42
+ raise av
43
+
44
+
45
+ def _av_available() -> bool:
46
+ return not isinstance(av, Exception)
47
+
48
+
49
+ # PyAV has some reference cycles
50
+ _CALLED_TIMES = 0
51
+ _GC_COLLECTION_INTERVAL = 10
52
+
53
+
54
+ def write_video(
55
+ filename: str,
56
+ video_array: torch.Tensor,
57
+ fps: float,
58
+ video_codec: str = "libx264",
59
+ options: Optional[Dict[str, Any]] = None,
60
+ audio_array: Optional[torch.Tensor] = None,
61
+ audio_fps: Optional[float] = None,
62
+ audio_codec: Optional[str] = None,
63
+ audio_options: Optional[Dict[str, Any]] = None,
64
+ ) -> None:
65
+ """
66
+ Writes a 4d tensor in [T, H, W, C] format in a video file
67
+
68
+ Args:
69
+ filename (str): path where the video will be saved
70
+ video_array (Tensor[T, H, W, C]): tensor containing the individual frames,
71
+ as a uint8 tensor in [T, H, W, C] format
72
+ fps (Number): video frames per second
73
+ video_codec (str): the name of the video codec, i.e. "libx264", "h264", etc.
74
+ options (Dict): dictionary containing options to be passed into the PyAV video stream
75
+ audio_array (Tensor[C, N]): tensor containing the audio, where C is the number of channels
76
+ and N is the number of samples
77
+ audio_fps (Number): audio sample rate, typically 44100 or 48000
78
+ audio_codec (str): the name of the audio codec, i.e. "mp3", "aac", etc.
79
+ audio_options (Dict): dictionary containing options to be passed into the PyAV audio stream
80
+ """
81
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
82
+ _log_api_usage_once(write_video)
83
+ _check_av_available()
84
+ video_array = torch.as_tensor(video_array, dtype=torch.uint8).numpy()
85
+
86
+ # PyAV does not support floating point numbers with decimal point
87
+ # and will throw OverflowException in case this is not the case
88
+ if isinstance(fps, float):
89
+ fps = np.round(fps)
90
+
91
+ with av.open(filename, mode="w") as container:
92
+ stream = container.add_stream(video_codec, rate=fps)
93
+ stream.width = video_array.shape[2]
94
+ stream.height = video_array.shape[1]
95
+ stream.pix_fmt = "yuv420p" if video_codec != "libx264rgb" else "rgb24"
96
+ stream.options = options or {}
97
+
98
+ if audio_array is not None:
99
+ audio_format_dtypes = {
100
+ "dbl": "<f8",
101
+ "dblp": "<f8",
102
+ "flt": "<f4",
103
+ "fltp": "<f4",
104
+ "s16": "<i2",
105
+ "s16p": "<i2",
106
+ "s32": "<i4",
107
+ "s32p": "<i4",
108
+ "u8": "u1",
109
+ "u8p": "u1",
110
+ }
111
+ a_stream = container.add_stream(audio_codec, rate=audio_fps)
112
+ a_stream.options = audio_options or {}
113
+
114
+ num_channels = audio_array.shape[0]
115
+ audio_layout = "stereo" if num_channels > 1 else "mono"
116
+ audio_sample_fmt = container.streams.audio[0].format.name
117
+
118
+ format_dtype = np.dtype(audio_format_dtypes[audio_sample_fmt])
119
+ audio_array = torch.as_tensor(audio_array).numpy().astype(format_dtype)
120
+
121
+ frame = av.AudioFrame.from_ndarray(audio_array, format=audio_sample_fmt, layout=audio_layout)
122
+
123
+ frame.sample_rate = audio_fps
124
+
125
+ for packet in a_stream.encode(frame):
126
+ container.mux(packet)
127
+
128
+ for packet in a_stream.encode():
129
+ container.mux(packet)
130
+
131
+ for img in video_array:
132
+ frame = av.VideoFrame.from_ndarray(img, format="rgb24")
133
+ frame.pict_type = "NONE"
134
+ for packet in stream.encode(frame):
135
+ container.mux(packet)
136
+
137
+ # Flush stream
138
+ for packet in stream.encode():
139
+ container.mux(packet)
140
+
141
+
142
+ def _read_from_stream(
143
+ container: "av.container.Container",
144
+ start_offset: float,
145
+ end_offset: float,
146
+ pts_unit: str,
147
+ stream: "av.stream.Stream",
148
+ stream_name: Dict[str, Optional[Union[int, Tuple[int, ...], List[int]]]],
149
+ ) -> List["av.frame.Frame"]:
150
+ global _CALLED_TIMES, _GC_COLLECTION_INTERVAL
151
+ _CALLED_TIMES += 1
152
+ if _CALLED_TIMES % _GC_COLLECTION_INTERVAL == _GC_COLLECTION_INTERVAL - 1:
153
+ gc.collect()
154
+
155
+ if pts_unit == "sec":
156
+ # TODO: we should change all of this from ground up to simply take
157
+ # sec and convert to MS in C++
158
+ start_offset = int(math.floor(start_offset * (1 / stream.time_base)))
159
+ if end_offset != float("inf"):
160
+ end_offset = int(math.ceil(end_offset * (1 / stream.time_base)))
161
+ else:
162
+ warnings.warn("The pts_unit 'pts' gives wrong results. Please use pts_unit 'sec'.")
163
+
164
+ frames = {}
165
+ should_buffer = True
166
+ max_buffer_size = 5
167
+ if stream.type == "video":
168
+ # DivX-style packed B-frames can have out-of-order pts (2 frames in a single pkt)
169
+ # so need to buffer some extra frames to sort everything
170
+ # properly
171
+ extradata = stream.codec_context.extradata
172
+ # overly complicated way of finding if `divx_packed` is set, following
173
+ # https://github.com/FFmpeg/FFmpeg/commit/d5a21172283572af587b3d939eba0091484d3263
174
+ if extradata and b"DivX" in extradata:
175
+ # can't use regex directly because of some weird characters sometimes...
176
+ pos = extradata.find(b"DivX")
177
+ d = extradata[pos:]
178
+ o = re.search(rb"DivX(\d+)Build(\d+)(\w)", d)
179
+ if o is None:
180
+ o = re.search(rb"DivX(\d+)b(\d+)(\w)", d)
181
+ if o is not None:
182
+ should_buffer = o.group(3) == b"p"
183
+ seek_offset = start_offset
184
+ # some files don't seek to the right location, so better be safe here
185
+ seek_offset = max(seek_offset - 1, 0)
186
+ if should_buffer:
187
+ # FIXME this is kind of a hack, but we will jump to the previous keyframe
188
+ # so this will be safe
189
+ seek_offset = max(seek_offset - max_buffer_size, 0)
190
+ try:
191
+ # TODO check if stream needs to always be the video stream here or not
192
+ container.seek(seek_offset, any_frame=False, backward=True, stream=stream)
193
+ except av.AVError:
194
+ # TODO add some warnings in this case
195
+ # print("Corrupted file?", container.name)
196
+ return []
197
+ buffer_count = 0
198
+ try:
199
+ for _idx, frame in enumerate(container.decode(**stream_name)):
200
+ frames[frame.pts] = frame
201
+ if frame.pts >= end_offset:
202
+ if should_buffer and buffer_count < max_buffer_size:
203
+ buffer_count += 1
204
+ continue
205
+ break
206
+ except av.AVError:
207
+ # TODO add a warning
208
+ pass
209
+ # ensure that the results are sorted wrt the pts
210
+ result = [frames[i] for i in sorted(frames) if start_offset <= frames[i].pts <= end_offset]
211
+ if len(frames) > 0 and start_offset > 0 and start_offset not in frames:
212
+ # if there is no frame that exactly matches the pts of start_offset
213
+ # add the last frame smaller than start_offset, to guarantee that
214
+ # we will have all the necessary data. This is most useful for audio
215
+ preceding_frames = [i for i in frames if i < start_offset]
216
+ if len(preceding_frames) > 0:
217
+ first_frame_pts = max(preceding_frames)
218
+ result.insert(0, frames[first_frame_pts])
219
+ return result
220
+
221
+
222
+ def _align_audio_frames(
223
+ aframes: torch.Tensor, audio_frames: List["av.frame.Frame"], ref_start: int, ref_end: float
224
+ ) -> torch.Tensor:
225
+ start, end = audio_frames[0].pts, audio_frames[-1].pts
226
+ total_aframes = aframes.shape[1]
227
+ step_per_aframe = (end - start + 1) / total_aframes
228
+ s_idx = 0
229
+ e_idx = total_aframes
230
+ if start < ref_start:
231
+ s_idx = int((ref_start - start) / step_per_aframe)
232
+ if end > ref_end:
233
+ e_idx = int((ref_end - end) / step_per_aframe)
234
+ return aframes[:, s_idx:e_idx]
235
+
236
+
237
+ def read_video(
238
+ filename: str,
239
+ start_pts: Union[float, Fraction] = 0,
240
+ end_pts: Optional[Union[float, Fraction]] = None,
241
+ pts_unit: str = "pts",
242
+ output_format: str = "THWC",
243
+ ) -> Tuple[torch.Tensor, torch.Tensor, Dict[str, Any]]:
244
+ """
245
+ Reads a video from a file, returning both the video frames as well as
246
+ the audio frames
247
+
248
+ Args:
249
+ filename (str): path to the video file
250
+ start_pts (int if pts_unit = 'pts', float / Fraction if pts_unit = 'sec', optional):
251
+ The start presentation time of the video
252
+ end_pts (int if pts_unit = 'pts', float / Fraction if pts_unit = 'sec', optional):
253
+ The end presentation time
254
+ pts_unit (str, optional): unit in which start_pts and end_pts values will be interpreted,
255
+ either 'pts' or 'sec'. Defaults to 'pts'.
256
+ output_format (str, optional): The format of the output video tensors. Can be either "THWC" (default) or "TCHW".
257
+
258
+ Returns:
259
+ vframes (Tensor[T, H, W, C] or Tensor[T, C, H, W]): the `T` video frames
260
+ aframes (Tensor[K, L]): the audio frames, where `K` is the number of channels and `L` is the number of points
261
+ info (Dict): metadata for the video and audio. Can contain the fields video_fps (float) and audio_fps (int)
262
+ """
263
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
264
+ _log_api_usage_once(read_video)
265
+
266
+ output_format = output_format.upper()
267
+ if output_format not in ("THWC", "TCHW"):
268
+ raise ValueError(f"output_format should be either 'THWC' or 'TCHW', got {output_format}.")
269
+
270
+ from torchvision import get_video_backend
271
+
272
+ if not os.path.exists(filename):
273
+ raise RuntimeError(f"File not found: {filename}")
274
+
275
+ if get_video_backend() != "pyav":
276
+ return _video_opt._read_video(filename, start_pts, end_pts, pts_unit)
277
+
278
+ _check_av_available()
279
+
280
+ if end_pts is None:
281
+ end_pts = float("inf")
282
+
283
+ if end_pts < start_pts:
284
+ raise ValueError(f"end_pts should be larger than start_pts, got start_pts={start_pts} and end_pts={end_pts}")
285
+
286
+ info = {}
287
+ video_frames = []
288
+ audio_frames = []
289
+ audio_timebase = _video_opt.default_timebase
290
+
291
+ try:
292
+ with av.open(filename, metadata_errors="ignore") as container:
293
+ if container.streams.audio:
294
+ audio_timebase = container.streams.audio[0].time_base
295
+ if container.streams.video:
296
+ video_frames = _read_from_stream(
297
+ container,
298
+ start_pts,
299
+ end_pts,
300
+ pts_unit,
301
+ container.streams.video[0],
302
+ {"video": 0},
303
+ )
304
+ video_fps = container.streams.video[0].average_rate
305
+ # guard against potentially corrupted files
306
+ if video_fps is not None:
307
+ info["video_fps"] = float(video_fps)
308
+
309
+ if container.streams.audio:
310
+ audio_frames = _read_from_stream(
311
+ container,
312
+ start_pts,
313
+ end_pts,
314
+ pts_unit,
315
+ container.streams.audio[0],
316
+ {"audio": 0},
317
+ )
318
+ info["audio_fps"] = container.streams.audio[0].rate
319
+
320
+ except av.AVError:
321
+ # TODO raise a warning?
322
+ pass
323
+
324
+ vframes_list = [frame.to_rgb().to_ndarray() for frame in video_frames]
325
+ aframes_list = [frame.to_ndarray() for frame in audio_frames]
326
+
327
+ if vframes_list:
328
+ vframes = torch.as_tensor(np.stack(vframes_list))
329
+ else:
330
+ vframes = torch.empty((0, 1, 1, 3), dtype=torch.uint8)
331
+
332
+ if aframes_list:
333
+ aframes = np.concatenate(aframes_list, 1)
334
+ aframes = torch.as_tensor(aframes)
335
+ if pts_unit == "sec":
336
+ start_pts = int(math.floor(start_pts * (1 / audio_timebase)))
337
+ if end_pts != float("inf"):
338
+ end_pts = int(math.ceil(end_pts * (1 / audio_timebase)))
339
+ aframes = _align_audio_frames(aframes, audio_frames, start_pts, end_pts)
340
+ else:
341
+ aframes = torch.empty((1, 0), dtype=torch.float32)
342
+
343
+ if output_format == "TCHW":
344
+ # [T,H,W,C] --> [T,C,H,W]
345
+ vframes = vframes.permute(0, 3, 1, 2)
346
+
347
+ return vframes, aframes, info
348
+
349
+
350
+ def _can_read_timestamps_from_packets(container: "av.container.Container") -> bool:
351
+ extradata = container.streams[0].codec_context.extradata
352
+ if extradata is None:
353
+ return False
354
+ if b"Lavc" in extradata:
355
+ return True
356
+ return False
357
+
358
+
359
+ def _decode_video_timestamps(container: "av.container.Container") -> List[int]:
360
+ if _can_read_timestamps_from_packets(container):
361
+ # fast path
362
+ return [x.pts for x in container.demux(video=0) if x.pts is not None]
363
+ else:
364
+ return [x.pts for x in container.decode(video=0) if x.pts is not None]
365
+
366
+
367
+ def read_video_timestamps(filename: str, pts_unit: str = "pts") -> Tuple[List[int], Optional[float]]:
368
+ """
369
+ List the video frames timestamps.
370
+
371
+ Note that the function decodes the whole video frame-by-frame.
372
+
373
+ Args:
374
+ filename (str): path to the video file
375
+ pts_unit (str, optional): unit in which timestamp values will be returned
376
+ either 'pts' or 'sec'. Defaults to 'pts'.
377
+
378
+ Returns:
379
+ pts (List[int] if pts_unit = 'pts', List[Fraction] if pts_unit = 'sec'):
380
+ presentation timestamps for each one of the frames in the video.
381
+ video_fps (float, optional): the frame rate for the video
382
+
383
+ """
384
+ if not torch.jit.is_scripting() and not torch.jit.is_tracing():
385
+ _log_api_usage_once(read_video_timestamps)
386
+ from torchvision import get_video_backend
387
+
388
+ if get_video_backend() != "pyav":
389
+ return _video_opt._read_video_timestamps(filename, pts_unit)
390
+
391
+ _check_av_available()
392
+
393
+ video_fps = None
394
+ pts = []
395
+
396
+ try:
397
+ with av.open(filename, metadata_errors="ignore") as container:
398
+ if container.streams.video:
399
+ video_stream = container.streams.video[0]
400
+ video_time_base = video_stream.time_base
401
+ try:
402
+ pts = _decode_video_timestamps(container)
403
+ except av.AVError:
404
+ warnings.warn(f"Failed decoding frames for file {filename}")
405
+ video_fps = float(video_stream.average_rate)
406
+ except av.AVError as e:
407
+ msg = f"Failed to open container for {filename}; Caught error: {e}"
408
+ warnings.warn(msg, RuntimeWarning)
409
+
410
+ pts.sort()
411
+
412
+ if pts_unit == "sec":
413
+ pts = [x * video_time_base for x in pts]
414
+
415
+ return pts, video_fps
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/__pycache__/_meta.cpython-38.pyc ADDED
Binary file (27.9 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/__pycache__/alexnet.cpython-38.pyc ADDED
Binary file (4.34 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/__pycache__/feature_extraction.cpython-38.pyc ADDED
Binary file (20.8 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/__pycache__/mobilenetv2.cpython-38.pyc ADDED
Binary file (8.23 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/detection/_utils.py ADDED
@@ -0,0 +1,538 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from collections import OrderedDict
3
+ from typing import Dict, List, Optional, Tuple
4
+
5
+ import torch
6
+ from torch import Tensor, nn
7
+ from torch.nn import functional as F
8
+ from torchvision.ops import FrozenBatchNorm2d, complete_box_iou_loss, distance_box_iou_loss, generalized_box_iou_loss
9
+
10
+
11
+ class BalancedPositiveNegativeSampler:
12
+ """
13
+ This class samples batches, ensuring that they contain a fixed proportion of positives
14
+ """
15
+
16
+ def __init__(self, batch_size_per_image: int, positive_fraction: float) -> None:
17
+ """
18
+ Args:
19
+ batch_size_per_image (int): number of elements to be selected per image
20
+ positive_fraction (float): percentage of positive elements per batch
21
+ """
22
+ self.batch_size_per_image = batch_size_per_image
23
+ self.positive_fraction = positive_fraction
24
+
25
+ def __call__(self, matched_idxs: List[Tensor]) -> Tuple[List[Tensor], List[Tensor]]:
26
+ """
27
+ Args:
28
+ matched idxs: list of tensors containing -1, 0 or positive values.
29
+ Each tensor corresponds to a specific image.
30
+ -1 values are ignored, 0 are considered as negatives and > 0 as
31
+ positives.
32
+
33
+ Returns:
34
+ pos_idx (list[tensor])
35
+ neg_idx (list[tensor])
36
+
37
+ Returns two lists of binary masks for each image.
38
+ The first list contains the positive elements that were selected,
39
+ and the second list the negative example.
40
+ """
41
+ pos_idx = []
42
+ neg_idx = []
43
+ for matched_idxs_per_image in matched_idxs:
44
+ positive = torch.where(matched_idxs_per_image >= 1)[0]
45
+ negative = torch.where(matched_idxs_per_image == 0)[0]
46
+
47
+ num_pos = int(self.batch_size_per_image * self.positive_fraction)
48
+ # protect against not enough positive examples
49
+ num_pos = min(positive.numel(), num_pos)
50
+ num_neg = self.batch_size_per_image - num_pos
51
+ # protect against not enough negative examples
52
+ num_neg = min(negative.numel(), num_neg)
53
+
54
+ # randomly select positive and negative examples
55
+ perm1 = torch.randperm(positive.numel(), device=positive.device)[:num_pos]
56
+ perm2 = torch.randperm(negative.numel(), device=negative.device)[:num_neg]
57
+
58
+ pos_idx_per_image = positive[perm1]
59
+ neg_idx_per_image = negative[perm2]
60
+
61
+ # create binary mask from indices
62
+ pos_idx_per_image_mask = torch.zeros_like(matched_idxs_per_image, dtype=torch.uint8)
63
+ neg_idx_per_image_mask = torch.zeros_like(matched_idxs_per_image, dtype=torch.uint8)
64
+
65
+ pos_idx_per_image_mask[pos_idx_per_image] = 1
66
+ neg_idx_per_image_mask[neg_idx_per_image] = 1
67
+
68
+ pos_idx.append(pos_idx_per_image_mask)
69
+ neg_idx.append(neg_idx_per_image_mask)
70
+
71
+ return pos_idx, neg_idx
72
+
73
+
74
+ @torch.jit._script_if_tracing
75
+ def encode_boxes(reference_boxes: Tensor, proposals: Tensor, weights: Tensor) -> Tensor:
76
+ """
77
+ Encode a set of proposals with respect to some
78
+ reference boxes
79
+
80
+ Args:
81
+ reference_boxes (Tensor): reference boxes
82
+ proposals (Tensor): boxes to be encoded
83
+ weights (Tensor[4]): the weights for ``(x, y, w, h)``
84
+ """
85
+
86
+ # perform some unpacking to make it JIT-fusion friendly
87
+ wx = weights[0]
88
+ wy = weights[1]
89
+ ww = weights[2]
90
+ wh = weights[3]
91
+
92
+ proposals_x1 = proposals[:, 0].unsqueeze(1)
93
+ proposals_y1 = proposals[:, 1].unsqueeze(1)
94
+ proposals_x2 = proposals[:, 2].unsqueeze(1)
95
+ proposals_y2 = proposals[:, 3].unsqueeze(1)
96
+
97
+ reference_boxes_x1 = reference_boxes[:, 0].unsqueeze(1)
98
+ reference_boxes_y1 = reference_boxes[:, 1].unsqueeze(1)
99
+ reference_boxes_x2 = reference_boxes[:, 2].unsqueeze(1)
100
+ reference_boxes_y2 = reference_boxes[:, 3].unsqueeze(1)
101
+
102
+ # implementation starts here
103
+ ex_widths = proposals_x2 - proposals_x1
104
+ ex_heights = proposals_y2 - proposals_y1
105
+ ex_ctr_x = proposals_x1 + 0.5 * ex_widths
106
+ ex_ctr_y = proposals_y1 + 0.5 * ex_heights
107
+
108
+ gt_widths = reference_boxes_x2 - reference_boxes_x1
109
+ gt_heights = reference_boxes_y2 - reference_boxes_y1
110
+ gt_ctr_x = reference_boxes_x1 + 0.5 * gt_widths
111
+ gt_ctr_y = reference_boxes_y1 + 0.5 * gt_heights
112
+
113
+ targets_dx = wx * (gt_ctr_x - ex_ctr_x) / ex_widths
114
+ targets_dy = wy * (gt_ctr_y - ex_ctr_y) / ex_heights
115
+ targets_dw = ww * torch.log(gt_widths / ex_widths)
116
+ targets_dh = wh * torch.log(gt_heights / ex_heights)
117
+
118
+ targets = torch.cat((targets_dx, targets_dy, targets_dw, targets_dh), dim=1)
119
+ return targets
120
+
121
+
122
+ class BoxCoder:
123
+ """
124
+ This class encodes and decodes a set of bounding boxes into
125
+ the representation used for training the regressors.
126
+ """
127
+
128
+ def __init__(
129
+ self, weights: Tuple[float, float, float, float], bbox_xform_clip: float = math.log(1000.0 / 16)
130
+ ) -> None:
131
+ """
132
+ Args:
133
+ weights (4-element tuple)
134
+ bbox_xform_clip (float)
135
+ """
136
+ self.weights = weights
137
+ self.bbox_xform_clip = bbox_xform_clip
138
+
139
+ def encode(self, reference_boxes: List[Tensor], proposals: List[Tensor]) -> List[Tensor]:
140
+ boxes_per_image = [len(b) for b in reference_boxes]
141
+ reference_boxes = torch.cat(reference_boxes, dim=0)
142
+ proposals = torch.cat(proposals, dim=0)
143
+ targets = self.encode_single(reference_boxes, proposals)
144
+ return targets.split(boxes_per_image, 0)
145
+
146
+ def encode_single(self, reference_boxes: Tensor, proposals: Tensor) -> Tensor:
147
+ """
148
+ Encode a set of proposals with respect to some
149
+ reference boxes
150
+
151
+ Args:
152
+ reference_boxes (Tensor): reference boxes
153
+ proposals (Tensor): boxes to be encoded
154
+ """
155
+ dtype = reference_boxes.dtype
156
+ device = reference_boxes.device
157
+ weights = torch.as_tensor(self.weights, dtype=dtype, device=device)
158
+ targets = encode_boxes(reference_boxes, proposals, weights)
159
+
160
+ return targets
161
+
162
+ def decode(self, rel_codes: Tensor, boxes: List[Tensor]) -> Tensor:
163
+ torch._assert(
164
+ isinstance(boxes, (list, tuple)),
165
+ "This function expects boxes of type list or tuple.",
166
+ )
167
+ torch._assert(
168
+ isinstance(rel_codes, torch.Tensor),
169
+ "This function expects rel_codes of type torch.Tensor.",
170
+ )
171
+ boxes_per_image = [b.size(0) for b in boxes]
172
+ concat_boxes = torch.cat(boxes, dim=0)
173
+ box_sum = 0
174
+ for val in boxes_per_image:
175
+ box_sum += val
176
+ if box_sum > 0:
177
+ rel_codes = rel_codes.reshape(box_sum, -1)
178
+ pred_boxes = self.decode_single(rel_codes, concat_boxes)
179
+ if box_sum > 0:
180
+ pred_boxes = pred_boxes.reshape(box_sum, -1, 4)
181
+ return pred_boxes
182
+
183
+ def decode_single(self, rel_codes: Tensor, boxes: Tensor) -> Tensor:
184
+ """
185
+ From a set of original boxes and encoded relative box offsets,
186
+ get the decoded boxes.
187
+
188
+ Args:
189
+ rel_codes (Tensor): encoded boxes
190
+ boxes (Tensor): reference boxes.
191
+ """
192
+
193
+ boxes = boxes.to(rel_codes.dtype)
194
+
195
+ widths = boxes[:, 2] - boxes[:, 0]
196
+ heights = boxes[:, 3] - boxes[:, 1]
197
+ ctr_x = boxes[:, 0] + 0.5 * widths
198
+ ctr_y = boxes[:, 1] + 0.5 * heights
199
+
200
+ wx, wy, ww, wh = self.weights
201
+ dx = rel_codes[:, 0::4] / wx
202
+ dy = rel_codes[:, 1::4] / wy
203
+ dw = rel_codes[:, 2::4] / ww
204
+ dh = rel_codes[:, 3::4] / wh
205
+
206
+ # Prevent sending too large values into torch.exp()
207
+ dw = torch.clamp(dw, max=self.bbox_xform_clip)
208
+ dh = torch.clamp(dh, max=self.bbox_xform_clip)
209
+
210
+ pred_ctr_x = dx * widths[:, None] + ctr_x[:, None]
211
+ pred_ctr_y = dy * heights[:, None] + ctr_y[:, None]
212
+ pred_w = torch.exp(dw) * widths[:, None]
213
+ pred_h = torch.exp(dh) * heights[:, None]
214
+
215
+ # Distance from center to box's corner.
216
+ c_to_c_h = torch.tensor(0.5, dtype=pred_ctr_y.dtype, device=pred_h.device) * pred_h
217
+ c_to_c_w = torch.tensor(0.5, dtype=pred_ctr_x.dtype, device=pred_w.device) * pred_w
218
+
219
+ pred_boxes1 = pred_ctr_x - c_to_c_w
220
+ pred_boxes2 = pred_ctr_y - c_to_c_h
221
+ pred_boxes3 = pred_ctr_x + c_to_c_w
222
+ pred_boxes4 = pred_ctr_y + c_to_c_h
223
+ pred_boxes = torch.stack((pred_boxes1, pred_boxes2, pred_boxes3, pred_boxes4), dim=2).flatten(1)
224
+ return pred_boxes
225
+
226
+
227
+ class BoxLinearCoder:
228
+ """
229
+ The linear box-to-box transform defined in FCOS. The transformation is parameterized
230
+ by the distance from the center of (square) src box to 4 edges of the target box.
231
+ """
232
+
233
+ def __init__(self, normalize_by_size: bool = True) -> None:
234
+ """
235
+ Args:
236
+ normalize_by_size (bool): normalize deltas by the size of src (anchor) boxes.
237
+ """
238
+ self.normalize_by_size = normalize_by_size
239
+
240
+ def encode_single(self, reference_boxes: Tensor, proposals: Tensor) -> Tensor:
241
+ """
242
+ Encode a set of proposals with respect to some reference boxes
243
+
244
+ Args:
245
+ reference_boxes (Tensor): reference boxes
246
+ proposals (Tensor): boxes to be encoded
247
+
248
+ Returns:
249
+ Tensor: the encoded relative box offsets that can be used to
250
+ decode the boxes.
251
+ """
252
+ # get the center of reference_boxes
253
+ reference_boxes_ctr_x = 0.5 * (reference_boxes[:, 0] + reference_boxes[:, 2])
254
+ reference_boxes_ctr_y = 0.5 * (reference_boxes[:, 1] + reference_boxes[:, 3])
255
+
256
+ # get box regression transformation deltas
257
+ target_l = reference_boxes_ctr_x - proposals[:, 0]
258
+ target_t = reference_boxes_ctr_y - proposals[:, 1]
259
+ target_r = proposals[:, 2] - reference_boxes_ctr_x
260
+ target_b = proposals[:, 3] - reference_boxes_ctr_y
261
+
262
+ targets = torch.stack((target_l, target_t, target_r, target_b), dim=1)
263
+ if self.normalize_by_size:
264
+ reference_boxes_w = reference_boxes[:, 2] - reference_boxes[:, 0]
265
+ reference_boxes_h = reference_boxes[:, 3] - reference_boxes[:, 1]
266
+ reference_boxes_size = torch.stack(
267
+ (reference_boxes_w, reference_boxes_h, reference_boxes_w, reference_boxes_h), dim=1
268
+ )
269
+ targets = targets / reference_boxes_size
270
+
271
+ return targets
272
+
273
+ def decode_single(self, rel_codes: Tensor, boxes: Tensor) -> Tensor:
274
+ """
275
+ From a set of original boxes and encoded relative box offsets,
276
+ get the decoded boxes.
277
+
278
+ Args:
279
+ rel_codes (Tensor): encoded boxes
280
+ boxes (Tensor): reference boxes.
281
+
282
+ Returns:
283
+ Tensor: the predicted boxes with the encoded relative box offsets.
284
+ """
285
+
286
+ boxes = boxes.to(rel_codes.dtype)
287
+
288
+ ctr_x = 0.5 * (boxes[:, 0] + boxes[:, 2])
289
+ ctr_y = 0.5 * (boxes[:, 1] + boxes[:, 3])
290
+ if self.normalize_by_size:
291
+ boxes_w = boxes[:, 2] - boxes[:, 0]
292
+ boxes_h = boxes[:, 3] - boxes[:, 1]
293
+ boxes_size = torch.stack((boxes_w, boxes_h, boxes_w, boxes_h), dim=1)
294
+ rel_codes = rel_codes * boxes_size
295
+
296
+ pred_boxes1 = ctr_x - rel_codes[:, 0]
297
+ pred_boxes2 = ctr_y - rel_codes[:, 1]
298
+ pred_boxes3 = ctr_x + rel_codes[:, 2]
299
+ pred_boxes4 = ctr_y + rel_codes[:, 3]
300
+ pred_boxes = torch.stack((pred_boxes1, pred_boxes2, pred_boxes3, pred_boxes4), dim=1)
301
+ return pred_boxes
302
+
303
+
304
+ class Matcher:
305
+ """
306
+ This class assigns to each predicted "element" (e.g., a box) a ground-truth
307
+ element. Each predicted element will have exactly zero or one matches; each
308
+ ground-truth element may be assigned to zero or more predicted elements.
309
+
310
+ Matching is based on the MxN match_quality_matrix, that characterizes how well
311
+ each (ground-truth, predicted)-pair match. For example, if the elements are
312
+ boxes, the matrix may contain box IoU overlap values.
313
+
314
+ The matcher returns a tensor of size N containing the index of the ground-truth
315
+ element m that matches to prediction n. If there is no match, a negative value
316
+ is returned.
317
+ """
318
+
319
+ BELOW_LOW_THRESHOLD = -1
320
+ BETWEEN_THRESHOLDS = -2
321
+
322
+ __annotations__ = {
323
+ "BELOW_LOW_THRESHOLD": int,
324
+ "BETWEEN_THRESHOLDS": int,
325
+ }
326
+
327
+ def __init__(self, high_threshold: float, low_threshold: float, allow_low_quality_matches: bool = False) -> None:
328
+ """
329
+ Args:
330
+ high_threshold (float): quality values greater than or equal to
331
+ this value are candidate matches.
332
+ low_threshold (float): a lower quality threshold used to stratify
333
+ matches into three levels:
334
+ 1) matches >= high_threshold
335
+ 2) BETWEEN_THRESHOLDS matches in [low_threshold, high_threshold)
336
+ 3) BELOW_LOW_THRESHOLD matches in [0, low_threshold)
337
+ allow_low_quality_matches (bool): if True, produce additional matches
338
+ for predictions that have only low-quality match candidates. See
339
+ set_low_quality_matches_ for more details.
340
+ """
341
+ self.BELOW_LOW_THRESHOLD = -1
342
+ self.BETWEEN_THRESHOLDS = -2
343
+ torch._assert(low_threshold <= high_threshold, "low_threshold should be <= high_threshold")
344
+ self.high_threshold = high_threshold
345
+ self.low_threshold = low_threshold
346
+ self.allow_low_quality_matches = allow_low_quality_matches
347
+
348
+ def __call__(self, match_quality_matrix: Tensor) -> Tensor:
349
+ """
350
+ Args:
351
+ match_quality_matrix (Tensor[float]): an MxN tensor, containing the
352
+ pairwise quality between M ground-truth elements and N predicted elements.
353
+
354
+ Returns:
355
+ matches (Tensor[int64]): an N tensor where N[i] is a matched gt in
356
+ [0, M - 1] or a negative value indicating that prediction i could not
357
+ be matched.
358
+ """
359
+ if match_quality_matrix.numel() == 0:
360
+ # empty targets or proposals not supported during training
361
+ if match_quality_matrix.shape[0] == 0:
362
+ raise ValueError("No ground-truth boxes available for one of the images during training")
363
+ else:
364
+ raise ValueError("No proposal boxes available for one of the images during training")
365
+
366
+ # match_quality_matrix is M (gt) x N (predicted)
367
+ # Max over gt elements (dim 0) to find best gt candidate for each prediction
368
+ matched_vals, matches = match_quality_matrix.max(dim=0)
369
+ if self.allow_low_quality_matches:
370
+ all_matches = matches.clone()
371
+ else:
372
+ all_matches = None # type: ignore[assignment]
373
+
374
+ # Assign candidate matches with low quality to negative (unassigned) values
375
+ below_low_threshold = matched_vals < self.low_threshold
376
+ between_thresholds = (matched_vals >= self.low_threshold) & (matched_vals < self.high_threshold)
377
+ matches[below_low_threshold] = self.BELOW_LOW_THRESHOLD
378
+ matches[between_thresholds] = self.BETWEEN_THRESHOLDS
379
+
380
+ if self.allow_low_quality_matches:
381
+ if all_matches is None:
382
+ torch._assert(False, "all_matches should not be None")
383
+ else:
384
+ self.set_low_quality_matches_(matches, all_matches, match_quality_matrix)
385
+
386
+ return matches
387
+
388
+ def set_low_quality_matches_(self, matches: Tensor, all_matches: Tensor, match_quality_matrix: Tensor) -> None:
389
+ """
390
+ Produce additional matches for predictions that have only low-quality matches.
391
+ Specifically, for each ground-truth find the set of predictions that have
392
+ maximum overlap with it (including ties); for each prediction in that set, if
393
+ it is unmatched, then match it to the ground-truth with which it has the highest
394
+ quality value.
395
+ """
396
+ # For each gt, find the prediction with which it has highest quality
397
+ highest_quality_foreach_gt, _ = match_quality_matrix.max(dim=1)
398
+ # Find highest quality match available, even if it is low, including ties
399
+ gt_pred_pairs_of_highest_quality = torch.where(match_quality_matrix == highest_quality_foreach_gt[:, None])
400
+ # Example gt_pred_pairs_of_highest_quality:
401
+ # tensor([[ 0, 39796],
402
+ # [ 1, 32055],
403
+ # [ 1, 32070],
404
+ # [ 2, 39190],
405
+ # [ 2, 40255],
406
+ # [ 3, 40390],
407
+ # [ 3, 41455],
408
+ # [ 4, 45470],
409
+ # [ 5, 45325],
410
+ # [ 5, 46390]])
411
+ # Each row is a (gt index, prediction index)
412
+ # Note how gt items 1, 2, 3, and 5 each have two ties
413
+
414
+ pred_inds_to_update = gt_pred_pairs_of_highest_quality[1]
415
+ matches[pred_inds_to_update] = all_matches[pred_inds_to_update]
416
+
417
+
418
+ class SSDMatcher(Matcher):
419
+ def __init__(self, threshold: float) -> None:
420
+ super().__init__(threshold, threshold, allow_low_quality_matches=False)
421
+
422
+ def __call__(self, match_quality_matrix: Tensor) -> Tensor:
423
+ matches = super().__call__(match_quality_matrix)
424
+
425
+ # For each gt, find the prediction with which it has the highest quality
426
+ _, highest_quality_pred_foreach_gt = match_quality_matrix.max(dim=1)
427
+ matches[highest_quality_pred_foreach_gt] = torch.arange(
428
+ highest_quality_pred_foreach_gt.size(0), dtype=torch.int64, device=highest_quality_pred_foreach_gt.device
429
+ )
430
+
431
+ return matches
432
+
433
+
434
+ def overwrite_eps(model: nn.Module, eps: float) -> None:
435
+ """
436
+ This method overwrites the default eps values of all the
437
+ FrozenBatchNorm2d layers of the model with the provided value.
438
+ This is necessary to address the BC-breaking change introduced
439
+ by the bug-fix at pytorch/vision#2933. The overwrite is applied
440
+ only when the pretrained weights are loaded to maintain compatibility
441
+ with previous versions.
442
+
443
+ Args:
444
+ model (nn.Module): The model on which we perform the overwrite.
445
+ eps (float): The new value of eps.
446
+ """
447
+ for module in model.modules():
448
+ if isinstance(module, FrozenBatchNorm2d):
449
+ module.eps = eps
450
+
451
+
452
+ def retrieve_out_channels(model: nn.Module, size: Tuple[int, int]) -> List[int]:
453
+ """
454
+ This method retrieves the number of output channels of a specific model.
455
+
456
+ Args:
457
+ model (nn.Module): The model for which we estimate the out_channels.
458
+ It should return a single Tensor or an OrderedDict[Tensor].
459
+ size (Tuple[int, int]): The size (wxh) of the input.
460
+
461
+ Returns:
462
+ out_channels (List[int]): A list of the output channels of the model.
463
+ """
464
+ in_training = model.training
465
+ model.eval()
466
+
467
+ with torch.no_grad():
468
+ # Use dummy data to retrieve the feature map sizes to avoid hard-coding their values
469
+ device = next(model.parameters()).device
470
+ tmp_img = torch.zeros((1, 3, size[1], size[0]), device=device)
471
+ features = model(tmp_img)
472
+ if isinstance(features, torch.Tensor):
473
+ features = OrderedDict([("0", features)])
474
+ out_channels = [x.size(1) for x in features.values()]
475
+
476
+ if in_training:
477
+ model.train()
478
+
479
+ return out_channels
480
+
481
+
482
+ @torch.jit.unused
483
+ def _fake_cast_onnx(v: Tensor) -> int:
484
+ return v # type: ignore[return-value]
485
+
486
+
487
+ def _topk_min(input: Tensor, orig_kval: int, axis: int) -> int:
488
+ """
489
+ ONNX spec requires the k-value to be less than or equal to the number of inputs along
490
+ provided dim. Certain models use the number of elements along a particular axis instead of K
491
+ if K exceeds the number of elements along that axis. Previously, python's min() function was
492
+ used to determine whether to use the provided k-value or the specified dim axis value.
493
+
494
+ However in cases where the model is being exported in tracing mode, python min() is
495
+ static causing the model to be traced incorrectly and eventually fail at the topk node.
496
+ In order to avoid this situation, in tracing mode, torch.min() is used instead.
497
+
498
+ Args:
499
+ input (Tensor): The orignal input tensor.
500
+ orig_kval (int): The provided k-value.
501
+ axis(int): Axis along which we retreive the input size.
502
+
503
+ Returns:
504
+ min_kval (int): Appropriately selected k-value.
505
+ """
506
+ if not torch.jit.is_tracing():
507
+ return min(orig_kval, input.size(axis))
508
+ axis_dim_val = torch._shape_as_tensor(input)[axis].unsqueeze(0)
509
+ min_kval = torch.min(torch.cat((torch.tensor([orig_kval], dtype=axis_dim_val.dtype), axis_dim_val), 0))
510
+ return _fake_cast_onnx(min_kval)
511
+
512
+
513
+ def _box_loss(
514
+ type: str,
515
+ box_coder: BoxCoder,
516
+ anchors_per_image: Tensor,
517
+ matched_gt_boxes_per_image: Tensor,
518
+ bbox_regression_per_image: Tensor,
519
+ cnf: Optional[Dict[str, float]] = None,
520
+ ) -> Tensor:
521
+ torch._assert(type in ["l1", "smooth_l1", "ciou", "diou", "giou"], f"Unsupported loss: {type}")
522
+
523
+ if type == "l1":
524
+ target_regression = box_coder.encode_single(matched_gt_boxes_per_image, anchors_per_image)
525
+ return F.l1_loss(bbox_regression_per_image, target_regression, reduction="sum")
526
+ elif type == "smooth_l1":
527
+ target_regression = box_coder.encode_single(matched_gt_boxes_per_image, anchors_per_image)
528
+ beta = cnf["beta"] if cnf is not None and "beta" in cnf else 1.0
529
+ return F.smooth_l1_loss(bbox_regression_per_image, target_regression, reduction="sum", beta=beta)
530
+ else:
531
+ bbox_per_image = box_coder.decode_single(bbox_regression_per_image, anchors_per_image)
532
+ eps = cnf["eps"] if cnf is not None and "eps" in cnf else 1e-7
533
+ if type == "ciou":
534
+ return complete_box_iou_loss(bbox_per_image, matched_gt_boxes_per_image, reduction="sum", eps=eps)
535
+ if type == "diou":
536
+ return distance_box_iou_loss(bbox_per_image, matched_gt_boxes_per_image, reduction="sum", eps=eps)
537
+ # otherwise giou
538
+ return generalized_box_iou_loss(bbox_per_image, matched_gt_boxes_per_image, reduction="sum", eps=eps)
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/detection/anchor_utils.py ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from typing import List, Optional
3
+
4
+ import torch
5
+ from torch import nn, Tensor
6
+
7
+ from .image_list import ImageList
8
+
9
+
10
+ class AnchorGenerator(nn.Module):
11
+ """
12
+ Module that generates anchors for a set of feature maps and
13
+ image sizes.
14
+
15
+ The module support computing anchors at multiple sizes and aspect ratios
16
+ per feature map. This module assumes aspect ratio = height / width for
17
+ each anchor.
18
+
19
+ sizes and aspect_ratios should have the same number of elements, and it should
20
+ correspond to the number of feature maps.
21
+
22
+ sizes[i] and aspect_ratios[i] can have an arbitrary number of elements,
23
+ and AnchorGenerator will output a set of sizes[i] * aspect_ratios[i] anchors
24
+ per spatial location for feature map i.
25
+
26
+ Args:
27
+ sizes (Tuple[Tuple[int]]):
28
+ aspect_ratios (Tuple[Tuple[float]]):
29
+ """
30
+
31
+ __annotations__ = {
32
+ "cell_anchors": List[torch.Tensor],
33
+ }
34
+
35
+ def __init__(
36
+ self,
37
+ sizes=((128, 256, 512),),
38
+ aspect_ratios=((0.5, 1.0, 2.0),),
39
+ ):
40
+ super().__init__()
41
+
42
+ if not isinstance(sizes[0], (list, tuple)):
43
+ # TODO change this
44
+ sizes = tuple((s,) for s in sizes)
45
+ if not isinstance(aspect_ratios[0], (list, tuple)):
46
+ aspect_ratios = (aspect_ratios,) * len(sizes)
47
+
48
+ self.sizes = sizes
49
+ self.aspect_ratios = aspect_ratios
50
+ self.cell_anchors = [
51
+ self.generate_anchors(size, aspect_ratio) for size, aspect_ratio in zip(sizes, aspect_ratios)
52
+ ]
53
+
54
+ # TODO: https://github.com/pytorch/pytorch/issues/26792
55
+ # For every (aspect_ratios, scales) combination, output a zero-centered anchor with those values.
56
+ # (scales, aspect_ratios) are usually an element of zip(self.scales, self.aspect_ratios)
57
+ # This method assumes aspect ratio = height / width for an anchor.
58
+ def generate_anchors(
59
+ self,
60
+ scales: List[int],
61
+ aspect_ratios: List[float],
62
+ dtype: torch.dtype = torch.float32,
63
+ device: torch.device = torch.device("cpu"),
64
+ ):
65
+ scales = torch.as_tensor(scales, dtype=dtype, device=device)
66
+ aspect_ratios = torch.as_tensor(aspect_ratios, dtype=dtype, device=device)
67
+ h_ratios = torch.sqrt(aspect_ratios)
68
+ w_ratios = 1 / h_ratios
69
+
70
+ ws = (w_ratios[:, None] * scales[None, :]).view(-1)
71
+ hs = (h_ratios[:, None] * scales[None, :]).view(-1)
72
+
73
+ base_anchors = torch.stack([-ws, -hs, ws, hs], dim=1) / 2
74
+ return base_anchors.round()
75
+
76
+ def set_cell_anchors(self, dtype: torch.dtype, device: torch.device):
77
+ self.cell_anchors = [cell_anchor.to(dtype=dtype, device=device) for cell_anchor in self.cell_anchors]
78
+
79
+ def num_anchors_per_location(self):
80
+ return [len(s) * len(a) for s, a in zip(self.sizes, self.aspect_ratios)]
81
+
82
+ # For every combination of (a, (g, s), i) in (self.cell_anchors, zip(grid_sizes, strides), 0:2),
83
+ # output g[i] anchors that are s[i] distance apart in direction i, with the same dimensions as a.
84
+ def grid_anchors(self, grid_sizes: List[List[int]], strides: List[List[Tensor]]) -> List[Tensor]:
85
+ anchors = []
86
+ cell_anchors = self.cell_anchors
87
+ torch._assert(cell_anchors is not None, "cell_anchors should not be None")
88
+ torch._assert(
89
+ len(grid_sizes) == len(strides) == len(cell_anchors),
90
+ "Anchors should be Tuple[Tuple[int]] because each feature "
91
+ "map could potentially have different sizes and aspect ratios. "
92
+ "There needs to be a match between the number of "
93
+ "feature maps passed and the number of sizes / aspect ratios specified.",
94
+ )
95
+
96
+ for size, stride, base_anchors in zip(grid_sizes, strides, cell_anchors):
97
+ grid_height, grid_width = size
98
+ stride_height, stride_width = stride
99
+ device = base_anchors.device
100
+
101
+ # For output anchor, compute [x_center, y_center, x_center, y_center]
102
+ shifts_x = torch.arange(0, grid_width, dtype=torch.int32, device=device) * stride_width
103
+ shifts_y = torch.arange(0, grid_height, dtype=torch.int32, device=device) * stride_height
104
+ shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing="ij")
105
+ shift_x = shift_x.reshape(-1)
106
+ shift_y = shift_y.reshape(-1)
107
+ shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=1)
108
+
109
+ # For every (base anchor, output anchor) pair,
110
+ # offset each zero-centered base anchor by the center of the output anchor.
111
+ anchors.append((shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4))
112
+
113
+ return anchors
114
+
115
+ def forward(self, image_list: ImageList, feature_maps: List[Tensor]) -> List[Tensor]:
116
+ grid_sizes = [feature_map.shape[-2:] for feature_map in feature_maps]
117
+ image_size = image_list.tensors.shape[-2:]
118
+ dtype, device = feature_maps[0].dtype, feature_maps[0].device
119
+ strides = [
120
+ [
121
+ torch.empty((), dtype=torch.int64, device=device).fill_(image_size[0] // g[0]),
122
+ torch.empty((), dtype=torch.int64, device=device).fill_(image_size[1] // g[1]),
123
+ ]
124
+ for g in grid_sizes
125
+ ]
126
+ self.set_cell_anchors(dtype, device)
127
+ anchors_over_all_feature_maps = self.grid_anchors(grid_sizes, strides)
128
+ anchors: List[List[torch.Tensor]] = []
129
+ for _ in range(len(image_list.image_sizes)):
130
+ anchors_in_image = [anchors_per_feature_map for anchors_per_feature_map in anchors_over_all_feature_maps]
131
+ anchors.append(anchors_in_image)
132
+ anchors = [torch.cat(anchors_per_image) for anchors_per_image in anchors]
133
+ return anchors
134
+
135
+
136
+ class DefaultBoxGenerator(nn.Module):
137
+ """
138
+ This module generates the default boxes of SSD for a set of feature maps and image sizes.
139
+
140
+ Args:
141
+ aspect_ratios (List[List[int]]): A list with all the aspect ratios used in each feature map.
142
+ min_ratio (float): The minimum scale :math:`\text{s}_{\text{min}}` of the default boxes used in the estimation
143
+ of the scales of each feature map. It is used only if the ``scales`` parameter is not provided.
144
+ max_ratio (float): The maximum scale :math:`\text{s}_{\text{max}}` of the default boxes used in the estimation
145
+ of the scales of each feature map. It is used only if the ``scales`` parameter is not provided.
146
+ scales (List[float]], optional): The scales of the default boxes. If not provided it will be estimated using
147
+ the ``min_ratio`` and ``max_ratio`` parameters.
148
+ steps (List[int]], optional): It's a hyper-parameter that affects the tiling of defalt boxes. If not provided
149
+ it will be estimated from the data.
150
+ clip (bool): Whether the standardized values of default boxes should be clipped between 0 and 1. The clipping
151
+ is applied while the boxes are encoded in format ``(cx, cy, w, h)``.
152
+ """
153
+
154
+ def __init__(
155
+ self,
156
+ aspect_ratios: List[List[int]],
157
+ min_ratio: float = 0.15,
158
+ max_ratio: float = 0.9,
159
+ scales: Optional[List[float]] = None,
160
+ steps: Optional[List[int]] = None,
161
+ clip: bool = True,
162
+ ):
163
+ super().__init__()
164
+ if steps is not None and len(aspect_ratios) != len(steps):
165
+ raise ValueError("aspect_ratios and steps should have the same length")
166
+ self.aspect_ratios = aspect_ratios
167
+ self.steps = steps
168
+ self.clip = clip
169
+ num_outputs = len(aspect_ratios)
170
+
171
+ # Estimation of default boxes scales
172
+ if scales is None:
173
+ if num_outputs > 1:
174
+ range_ratio = max_ratio - min_ratio
175
+ self.scales = [min_ratio + range_ratio * k / (num_outputs - 1.0) for k in range(num_outputs)]
176
+ self.scales.append(1.0)
177
+ else:
178
+ self.scales = [min_ratio, max_ratio]
179
+ else:
180
+ self.scales = scales
181
+
182
+ self._wh_pairs = self._generate_wh_pairs(num_outputs)
183
+
184
+ def _generate_wh_pairs(
185
+ self, num_outputs: int, dtype: torch.dtype = torch.float32, device: torch.device = torch.device("cpu")
186
+ ) -> List[Tensor]:
187
+ _wh_pairs: List[Tensor] = []
188
+ for k in range(num_outputs):
189
+ # Adding the 2 default width-height pairs for aspect ratio 1 and scale s'k
190
+ s_k = self.scales[k]
191
+ s_prime_k = math.sqrt(self.scales[k] * self.scales[k + 1])
192
+ wh_pairs = [[s_k, s_k], [s_prime_k, s_prime_k]]
193
+
194
+ # Adding 2 pairs for each aspect ratio of the feature map k
195
+ for ar in self.aspect_ratios[k]:
196
+ sq_ar = math.sqrt(ar)
197
+ w = self.scales[k] * sq_ar
198
+ h = self.scales[k] / sq_ar
199
+ wh_pairs.extend([[w, h], [h, w]])
200
+
201
+ _wh_pairs.append(torch.as_tensor(wh_pairs, dtype=dtype, device=device))
202
+ return _wh_pairs
203
+
204
+ def num_anchors_per_location(self):
205
+ # Estimate num of anchors based on aspect ratios: 2 default boxes + 2 * ratios of feaure map.
206
+ return [2 + 2 * len(r) for r in self.aspect_ratios]
207
+
208
+ # Default Boxes calculation based on page 6 of SSD paper
209
+ def _grid_default_boxes(
210
+ self, grid_sizes: List[List[int]], image_size: List[int], dtype: torch.dtype = torch.float32
211
+ ) -> Tensor:
212
+ default_boxes = []
213
+ for k, f_k in enumerate(grid_sizes):
214
+ # Now add the default boxes for each width-height pair
215
+ if self.steps is not None:
216
+ x_f_k = image_size[0] / self.steps[k]
217
+ y_f_k = image_size[1] / self.steps[k]
218
+ else:
219
+ y_f_k, x_f_k = f_k
220
+
221
+ shifts_x = ((torch.arange(0, f_k[1]) + 0.5) / x_f_k).to(dtype=dtype)
222
+ shifts_y = ((torch.arange(0, f_k[0]) + 0.5) / y_f_k).to(dtype=dtype)
223
+ shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing="ij")
224
+ shift_x = shift_x.reshape(-1)
225
+ shift_y = shift_y.reshape(-1)
226
+
227
+ shifts = torch.stack((shift_x, shift_y) * len(self._wh_pairs[k]), dim=-1).reshape(-1, 2)
228
+ # Clipping the default boxes while the boxes are encoded in format (cx, cy, w, h)
229
+ _wh_pair = self._wh_pairs[k].clamp(min=0, max=1) if self.clip else self._wh_pairs[k]
230
+ wh_pairs = _wh_pair.repeat((f_k[0] * f_k[1]), 1)
231
+
232
+ default_box = torch.cat((shifts, wh_pairs), dim=1)
233
+
234
+ default_boxes.append(default_box)
235
+
236
+ return torch.cat(default_boxes, dim=0)
237
+
238
+ def __repr__(self) -> str:
239
+ s = (
240
+ f"{self.__class__.__name__}("
241
+ f"aspect_ratios={self.aspect_ratios}"
242
+ f", clip={self.clip}"
243
+ f", scales={self.scales}"
244
+ f", steps={self.steps}"
245
+ ")"
246
+ )
247
+ return s
248
+
249
+ def forward(self, image_list: ImageList, feature_maps: List[Tensor]) -> List[Tensor]:
250
+ grid_sizes = [feature_map.shape[-2:] for feature_map in feature_maps]
251
+ image_size = image_list.tensors.shape[-2:]
252
+ dtype, device = feature_maps[0].dtype, feature_maps[0].device
253
+ default_boxes = self._grid_default_boxes(grid_sizes, image_size, dtype=dtype)
254
+ default_boxes = default_boxes.to(device)
255
+
256
+ dboxes = []
257
+ x_y_size = torch.tensor([image_size[1], image_size[0]], device=default_boxes.device)
258
+ for _ in image_list.image_sizes:
259
+ dboxes_in_image = default_boxes
260
+ dboxes_in_image = torch.cat(
261
+ [
262
+ (dboxes_in_image[:, :2] - 0.5 * dboxes_in_image[:, 2:]) * x_y_size,
263
+ (dboxes_in_image[:, :2] + 0.5 * dboxes_in_image[:, 2:]) * x_y_size,
264
+ ],
265
+ -1,
266
+ )
267
+ dboxes.append(dboxes_in_image)
268
+ return dboxes
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/detection/generalized_rcnn.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Implements the Generalized R-CNN framework
3
+ """
4
+
5
+ import warnings
6
+ from collections import OrderedDict
7
+ from typing import Tuple, List, Dict, Optional, Union
8
+
9
+ import torch
10
+ from torch import nn, Tensor
11
+
12
+ from ...utils import _log_api_usage_once
13
+
14
+
15
+ class GeneralizedRCNN(nn.Module):
16
+ """
17
+ Main class for Generalized R-CNN.
18
+
19
+ Args:
20
+ backbone (nn.Module):
21
+ rpn (nn.Module):
22
+ roi_heads (nn.Module): takes the features + the proposals from the RPN and computes
23
+ detections / masks from it.
24
+ transform (nn.Module): performs the data transformation from the inputs to feed into
25
+ the model
26
+ """
27
+
28
+ def __init__(self, backbone: nn.Module, rpn: nn.Module, roi_heads: nn.Module, transform: nn.Module) -> None:
29
+ super().__init__()
30
+ _log_api_usage_once(self)
31
+ self.transform = transform
32
+ self.backbone = backbone
33
+ self.rpn = rpn
34
+ self.roi_heads = roi_heads
35
+ # used only on torchscript mode
36
+ self._has_warned = False
37
+
38
+ @torch.jit.unused
39
+ def eager_outputs(self, losses, detections):
40
+ # type: (Dict[str, Tensor], List[Dict[str, Tensor]]) -> Union[Dict[str, Tensor], List[Dict[str, Tensor]]]
41
+ if self.training:
42
+ return losses
43
+
44
+ return detections
45
+
46
+ def forward(self, images, targets=None):
47
+ # type: (List[Tensor], Optional[List[Dict[str, Tensor]]]) -> Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]]
48
+ """
49
+ Args:
50
+ images (list[Tensor]): images to be processed
51
+ targets (list[Dict[str, Tensor]]): ground-truth boxes present in the image (optional)
52
+
53
+ Returns:
54
+ result (list[BoxList] or dict[Tensor]): the output from the model.
55
+ During training, it returns a dict[Tensor] which contains the losses.
56
+ During testing, it returns list[BoxList] contains additional fields
57
+ like `scores`, `labels` and `mask` (for Mask R-CNN models).
58
+
59
+ """
60
+ if self.training:
61
+ if targets is None:
62
+ torch._assert(False, "targets should not be none when in training mode")
63
+ else:
64
+ for target in targets:
65
+ boxes = target["boxes"]
66
+ if isinstance(boxes, torch.Tensor):
67
+ torch._assert(
68
+ len(boxes.shape) == 2 and boxes.shape[-1] == 4,
69
+ f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}.",
70
+ )
71
+ else:
72
+ torch._assert(False, f"Expected target boxes to be of type Tensor, got {type(boxes)}.")
73
+
74
+ original_image_sizes: List[Tuple[int, int]] = []
75
+ for img in images:
76
+ val = img.shape[-2:]
77
+ torch._assert(
78
+ len(val) == 2,
79
+ f"expecting the last two dimensions of the Tensor to be H and W instead got {img.shape[-2:]}",
80
+ )
81
+ original_image_sizes.append((val[0], val[1]))
82
+
83
+ images, targets = self.transform(images, targets)
84
+
85
+ # Check for degenerate boxes
86
+ # TODO: Move this to a function
87
+ if targets is not None:
88
+ for target_idx, target in enumerate(targets):
89
+ boxes = target["boxes"]
90
+ degenerate_boxes = boxes[:, 2:] <= boxes[:, :2]
91
+ if degenerate_boxes.any():
92
+ # print the first degenerate box
93
+ bb_idx = torch.where(degenerate_boxes.any(dim=1))[0][0]
94
+ degen_bb: List[float] = boxes[bb_idx].tolist()
95
+ torch._assert(
96
+ False,
97
+ "All bounding boxes should have positive height and width."
98
+ f" Found invalid box {degen_bb} for target at index {target_idx}.",
99
+ )
100
+
101
+ features = self.backbone(images.tensors)
102
+ if isinstance(features, torch.Tensor):
103
+ features = OrderedDict([("0", features)])
104
+ proposals, proposal_losses = self.rpn(images, features, targets)
105
+ detections, detector_losses = self.roi_heads(features, proposals, images.image_sizes, targets)
106
+ detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes) # type: ignore[operator]
107
+
108
+ losses = {}
109
+ losses.update(detector_losses)
110
+ losses.update(proposal_losses)
111
+
112
+ if torch.jit.is_scripting():
113
+ if not self._has_warned:
114
+ warnings.warn("RCNN always returns a (Losses, Detections) tuple in scripting")
115
+ self._has_warned = True
116
+ return losses, detections
117
+ else:
118
+ return self.eager_outputs(losses, detections)
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/detection/ssdlite.py ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import warnings
2
+ from collections import OrderedDict
3
+ from functools import partial
4
+ from typing import Any, Callable, Dict, List, Optional, Union
5
+
6
+ import torch
7
+ from torch import nn, Tensor
8
+
9
+ from ...ops.misc import Conv2dNormActivation
10
+ from ...transforms._presets import ObjectDetection
11
+ from ...utils import _log_api_usage_once
12
+ from .. import mobilenet
13
+ from .._api import WeightsEnum, Weights
14
+ from .._meta import _COCO_CATEGORIES
15
+ from .._utils import handle_legacy_interface, _ovewrite_value_param
16
+ from ..mobilenetv3 import MobileNet_V3_Large_Weights, mobilenet_v3_large
17
+ from . import _utils as det_utils
18
+ from .anchor_utils import DefaultBoxGenerator
19
+ from .backbone_utils import _validate_trainable_layers
20
+ from .ssd import SSD, SSDScoringHead
21
+
22
+
23
+ __all__ = [
24
+ "SSDLite320_MobileNet_V3_Large_Weights",
25
+ "ssdlite320_mobilenet_v3_large",
26
+ ]
27
+
28
+
29
+ # Building blocks of SSDlite as described in section 6.2 of MobileNetV2 paper
30
+ def _prediction_block(
31
+ in_channels: int, out_channels: int, kernel_size: int, norm_layer: Callable[..., nn.Module]
32
+ ) -> nn.Sequential:
33
+ return nn.Sequential(
34
+ # 3x3 depthwise with stride 1 and padding 1
35
+ Conv2dNormActivation(
36
+ in_channels,
37
+ in_channels,
38
+ kernel_size=kernel_size,
39
+ groups=in_channels,
40
+ norm_layer=norm_layer,
41
+ activation_layer=nn.ReLU6,
42
+ ),
43
+ # 1x1 projetion to output channels
44
+ nn.Conv2d(in_channels, out_channels, 1),
45
+ )
46
+
47
+
48
+ def _extra_block(in_channels: int, out_channels: int, norm_layer: Callable[..., nn.Module]) -> nn.Sequential:
49
+ activation = nn.ReLU6
50
+ intermediate_channels = out_channels // 2
51
+ return nn.Sequential(
52
+ # 1x1 projection to half output channels
53
+ Conv2dNormActivation(
54
+ in_channels, intermediate_channels, kernel_size=1, norm_layer=norm_layer, activation_layer=activation
55
+ ),
56
+ # 3x3 depthwise with stride 2 and padding 1
57
+ Conv2dNormActivation(
58
+ intermediate_channels,
59
+ intermediate_channels,
60
+ kernel_size=3,
61
+ stride=2,
62
+ groups=intermediate_channels,
63
+ norm_layer=norm_layer,
64
+ activation_layer=activation,
65
+ ),
66
+ # 1x1 projetion to output channels
67
+ Conv2dNormActivation(
68
+ intermediate_channels, out_channels, kernel_size=1, norm_layer=norm_layer, activation_layer=activation
69
+ ),
70
+ )
71
+
72
+
73
+ def _normal_init(conv: nn.Module):
74
+ for layer in conv.modules():
75
+ if isinstance(layer, nn.Conv2d):
76
+ torch.nn.init.normal_(layer.weight, mean=0.0, std=0.03)
77
+ if layer.bias is not None:
78
+ torch.nn.init.constant_(layer.bias, 0.0)
79
+
80
+
81
+ class SSDLiteHead(nn.Module):
82
+ def __init__(
83
+ self, in_channels: List[int], num_anchors: List[int], num_classes: int, norm_layer: Callable[..., nn.Module]
84
+ ):
85
+ super().__init__()
86
+ self.classification_head = SSDLiteClassificationHead(in_channels, num_anchors, num_classes, norm_layer)
87
+ self.regression_head = SSDLiteRegressionHead(in_channels, num_anchors, norm_layer)
88
+
89
+ def forward(self, x: List[Tensor]) -> Dict[str, Tensor]:
90
+ return {
91
+ "bbox_regression": self.regression_head(x),
92
+ "cls_logits": self.classification_head(x),
93
+ }
94
+
95
+
96
+ class SSDLiteClassificationHead(SSDScoringHead):
97
+ def __init__(
98
+ self, in_channels: List[int], num_anchors: List[int], num_classes: int, norm_layer: Callable[..., nn.Module]
99
+ ):
100
+ cls_logits = nn.ModuleList()
101
+ for channels, anchors in zip(in_channels, num_anchors):
102
+ cls_logits.append(_prediction_block(channels, num_classes * anchors, 3, norm_layer))
103
+ _normal_init(cls_logits)
104
+ super().__init__(cls_logits, num_classes)
105
+
106
+
107
+ class SSDLiteRegressionHead(SSDScoringHead):
108
+ def __init__(self, in_channels: List[int], num_anchors: List[int], norm_layer: Callable[..., nn.Module]):
109
+ bbox_reg = nn.ModuleList()
110
+ for channels, anchors in zip(in_channels, num_anchors):
111
+ bbox_reg.append(_prediction_block(channels, 4 * anchors, 3, norm_layer))
112
+ _normal_init(bbox_reg)
113
+ super().__init__(bbox_reg, 4)
114
+
115
+
116
+ class SSDLiteFeatureExtractorMobileNet(nn.Module):
117
+ def __init__(
118
+ self,
119
+ backbone: nn.Module,
120
+ c4_pos: int,
121
+ norm_layer: Callable[..., nn.Module],
122
+ width_mult: float = 1.0,
123
+ min_depth: int = 16,
124
+ ):
125
+ super().__init__()
126
+ _log_api_usage_once(self)
127
+
128
+ if backbone[c4_pos].use_res_connect:
129
+ raise ValueError("backbone[c4_pos].use_res_connect should be False")
130
+
131
+ self.features = nn.Sequential(
132
+ # As described in section 6.3 of MobileNetV3 paper
133
+ nn.Sequential(*backbone[:c4_pos], backbone[c4_pos].block[0]), # from start until C4 expansion layer
134
+ nn.Sequential(backbone[c4_pos].block[1:], *backbone[c4_pos + 1 :]), # from C4 depthwise until end
135
+ )
136
+
137
+ get_depth = lambda d: max(min_depth, int(d * width_mult)) # noqa: E731
138
+ extra = nn.ModuleList(
139
+ [
140
+ _extra_block(backbone[-1].out_channels, get_depth(512), norm_layer),
141
+ _extra_block(get_depth(512), get_depth(256), norm_layer),
142
+ _extra_block(get_depth(256), get_depth(256), norm_layer),
143
+ _extra_block(get_depth(256), get_depth(128), norm_layer),
144
+ ]
145
+ )
146
+ _normal_init(extra)
147
+
148
+ self.extra = extra
149
+
150
+ def forward(self, x: Tensor) -> Dict[str, Tensor]:
151
+ # Get feature maps from backbone and extra. Can't be refactored due to JIT limitations.
152
+ output = []
153
+ for block in self.features:
154
+ x = block(x)
155
+ output.append(x)
156
+
157
+ for block in self.extra:
158
+ x = block(x)
159
+ output.append(x)
160
+
161
+ return OrderedDict([(str(i), v) for i, v in enumerate(output)])
162
+
163
+
164
+ def _mobilenet_extractor(
165
+ backbone: Union[mobilenet.MobileNetV2, mobilenet.MobileNetV3],
166
+ trainable_layers: int,
167
+ norm_layer: Callable[..., nn.Module],
168
+ ):
169
+ backbone = backbone.features
170
+ # Gather the indices of blocks which are strided. These are the locations of C1, ..., Cn-1 blocks.
171
+ # The first and last blocks are always included because they are the C0 (conv1) and Cn.
172
+ stage_indices = [0] + [i for i, b in enumerate(backbone) if getattr(b, "_is_cn", False)] + [len(backbone) - 1]
173
+ num_stages = len(stage_indices)
174
+
175
+ # find the index of the layer from which we wont freeze
176
+ if not 0 <= trainable_layers <= num_stages:
177
+ raise ValueError("trainable_layers should be in the range [0, {num_stages}], instead got {trainable_layers}")
178
+ freeze_before = len(backbone) if trainable_layers == 0 else stage_indices[num_stages - trainable_layers]
179
+
180
+ for b in backbone[:freeze_before]:
181
+ for parameter in b.parameters():
182
+ parameter.requires_grad_(False)
183
+
184
+ return SSDLiteFeatureExtractorMobileNet(backbone, stage_indices[-2], norm_layer)
185
+
186
+
187
+ class SSDLite320_MobileNet_V3_Large_Weights(WeightsEnum):
188
+ COCO_V1 = Weights(
189
+ url="https://download.pytorch.org/models/ssdlite320_mobilenet_v3_large_coco-a79551df.pth",
190
+ transforms=ObjectDetection,
191
+ meta={
192
+ "num_params": 3440060,
193
+ "categories": _COCO_CATEGORIES,
194
+ "min_size": (1, 1),
195
+ "recipe": "https://github.com/pytorch/vision/tree/main/references/detection#ssdlite320-mobilenetv3-large",
196
+ "_metrics": {
197
+ "COCO-val2017": {
198
+ "box_map": 21.3,
199
+ }
200
+ },
201
+ "_docs": """These weights were produced by following a similar training recipe as on the paper.""",
202
+ },
203
+ )
204
+ DEFAULT = COCO_V1
205
+
206
+
207
+ @handle_legacy_interface(
208
+ weights=("pretrained", SSDLite320_MobileNet_V3_Large_Weights.COCO_V1),
209
+ weights_backbone=("pretrained_backbone", MobileNet_V3_Large_Weights.IMAGENET1K_V1),
210
+ )
211
+ def ssdlite320_mobilenet_v3_large(
212
+ *,
213
+ weights: Optional[SSDLite320_MobileNet_V3_Large_Weights] = None,
214
+ progress: bool = True,
215
+ num_classes: Optional[int] = None,
216
+ weights_backbone: Optional[MobileNet_V3_Large_Weights] = MobileNet_V3_Large_Weights.IMAGENET1K_V1,
217
+ trainable_backbone_layers: Optional[int] = None,
218
+ norm_layer: Optional[Callable[..., nn.Module]] = None,
219
+ **kwargs: Any,
220
+ ) -> SSD:
221
+ """SSDlite model architecture with input size 320x320 and a MobileNetV3 Large backbone, as
222
+ described at `Searching for MobileNetV3 <https://arxiv.org/abs/1905.02244>`__ and
223
+ `MobileNetV2: Inverted Residuals and Linear Bottlenecks <https://arxiv.org/abs/1801.04381>`__.
224
+
225
+ .. betastatus:: detection module
226
+
227
+ See :func:`~torchvision.models.detection.ssd300_vgg16` for more details.
228
+
229
+ Example:
230
+
231
+ >>> model = torchvision.models.detection.ssdlite320_mobilenet_v3_large(weights=SSDLite320_MobileNet_V3_Large_Weights.DEFAULT)
232
+ >>> model.eval()
233
+ >>> x = [torch.rand(3, 320, 320), torch.rand(3, 500, 400)]
234
+ >>> predictions = model(x)
235
+
236
+ Args:
237
+ weights (:class:`~torchvision.models.detection.SSDLite320_MobileNet_V3_Large_Weights`, optional): The
238
+ pretrained weights to use. See
239
+ :class:`~torchvision.models.detection.SSDLite320_MobileNet_V3_Large_Weights` below for
240
+ more details, and possible values. By default, no pre-trained
241
+ weights are used.
242
+ progress (bool, optional): If True, displays a progress bar of the
243
+ download to stderr. Default is True.
244
+ num_classes (int, optional): number of output classes of the model
245
+ (including the background).
246
+ weights_backbone (:class:`~torchvision.models.MobileNet_V3_Large_Weights`, optional): The pretrained
247
+ weights for the backbone.
248
+ trainable_backbone_layers (int, optional): number of trainable (not frozen) layers
249
+ starting from final block. Valid values are between 0 and 6, with 6 meaning all
250
+ backbone layers are trainable. If ``None`` is passed (the default) this value is
251
+ set to 6.
252
+ norm_layer (callable, optional): Module specifying the normalization layer to use.
253
+ **kwargs: parameters passed to the ``torchvision.models.detection.ssd.SSD``
254
+ base class. Please refer to the `source code
255
+ <https://github.com/pytorch/vision/blob/main/torchvision/models/detection/ssd.py>`_
256
+ for more details about this class.
257
+
258
+ .. autoclass:: torchvision.models.detection.SSDLite320_MobileNet_V3_Large_Weights
259
+ :members:
260
+ """
261
+
262
+ weights = SSDLite320_MobileNet_V3_Large_Weights.verify(weights)
263
+ weights_backbone = MobileNet_V3_Large_Weights.verify(weights_backbone)
264
+
265
+ if "size" in kwargs:
266
+ warnings.warn("The size of the model is already fixed; ignoring the parameter.")
267
+
268
+ if weights is not None:
269
+ weights_backbone = None
270
+ num_classes = _ovewrite_value_param(num_classes, len(weights.meta["categories"]))
271
+ elif num_classes is None:
272
+ num_classes = 91
273
+
274
+ trainable_backbone_layers = _validate_trainable_layers(
275
+ weights is not None or weights_backbone is not None, trainable_backbone_layers, 6, 6
276
+ )
277
+
278
+ # Enable reduced tail if no pretrained backbone is selected. See Table 6 of MobileNetV3 paper.
279
+ reduce_tail = weights_backbone is None
280
+
281
+ if norm_layer is None:
282
+ norm_layer = partial(nn.BatchNorm2d, eps=0.001, momentum=0.03)
283
+
284
+ backbone = mobilenet_v3_large(
285
+ weights=weights_backbone, progress=progress, norm_layer=norm_layer, reduced_tail=reduce_tail, **kwargs
286
+ )
287
+ if weights_backbone is None:
288
+ # Change the default initialization scheme if not pretrained
289
+ _normal_init(backbone)
290
+ backbone = _mobilenet_extractor(
291
+ backbone,
292
+ trainable_backbone_layers,
293
+ norm_layer,
294
+ )
295
+
296
+ size = (320, 320)
297
+ anchor_generator = DefaultBoxGenerator([[2, 3] for _ in range(6)], min_ratio=0.2, max_ratio=0.95)
298
+ out_channels = det_utils.retrieve_out_channels(backbone, size)
299
+ num_anchors = anchor_generator.num_anchors_per_location()
300
+ if len(out_channels) != len(anchor_generator.aspect_ratios):
301
+ raise ValueError(
302
+ f"The length of the output channels from the backbone {len(out_channels)} do not match the length of the anchor generator aspect ratios {len(anchor_generator.aspect_ratios)}"
303
+ )
304
+
305
+ defaults = {
306
+ "score_thresh": 0.001,
307
+ "nms_thresh": 0.55,
308
+ "detections_per_img": 300,
309
+ "topk_candidates": 300,
310
+ # Rescale the input in a way compatible to the backbone:
311
+ # The following mean/std rescale the data from [0, 1] to [-1, 1]
312
+ "image_mean": [0.5, 0.5, 0.5],
313
+ "image_std": [0.5, 0.5, 0.5],
314
+ }
315
+ kwargs: Any = {**defaults, **kwargs}
316
+ model = SSD(
317
+ backbone,
318
+ anchor_generator,
319
+ size,
320
+ num_classes,
321
+ head=SSDLiteHead(out_channels, num_anchors, num_classes, norm_layer),
322
+ **kwargs,
323
+ )
324
+
325
+ if weights is not None:
326
+ model.load_state_dict(weights.get_state_dict(progress=progress))
327
+
328
+ return model
329
+
330
+
331
+ # The dictionary below is internal implementation detail and will be removed in v0.15
332
+ from .._utils import _ModelURLs
333
+
334
+
335
+ model_urls = _ModelURLs(
336
+ {
337
+ "ssdlite320_mobilenet_v3_large_coco": SSDLite320_MobileNet_V3_Large_Weights.COCO_V1.url,
338
+ }
339
+ )
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/detection/transform.py ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from typing import List, Tuple, Dict, Optional, Any
3
+
4
+ import torch
5
+ import torchvision
6
+ from torch import nn, Tensor
7
+
8
+ from .image_list import ImageList
9
+ from .roi_heads import paste_masks_in_image
10
+
11
+
12
+ @torch.jit.unused
13
+ def _get_shape_onnx(image: Tensor) -> Tensor:
14
+ from torch.onnx import operators
15
+
16
+ return operators.shape_as_tensor(image)[-2:]
17
+
18
+
19
+ @torch.jit.unused
20
+ def _fake_cast_onnx(v: Tensor) -> float:
21
+ # ONNX requires a tensor but here we fake its type for JIT.
22
+ return v
23
+
24
+
25
+ def _resize_image_and_masks(
26
+ image: Tensor,
27
+ self_min_size: float,
28
+ self_max_size: float,
29
+ target: Optional[Dict[str, Tensor]] = None,
30
+ fixed_size: Optional[Tuple[int, int]] = None,
31
+ ) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]:
32
+ if torchvision._is_tracing():
33
+ im_shape = _get_shape_onnx(image)
34
+ else:
35
+ im_shape = torch.tensor(image.shape[-2:])
36
+
37
+ size: Optional[List[int]] = None
38
+ scale_factor: Optional[float] = None
39
+ recompute_scale_factor: Optional[bool] = None
40
+ if fixed_size is not None:
41
+ size = [fixed_size[1], fixed_size[0]]
42
+ else:
43
+ min_size = torch.min(im_shape).to(dtype=torch.float32)
44
+ max_size = torch.max(im_shape).to(dtype=torch.float32)
45
+ scale = torch.min(self_min_size / min_size, self_max_size / max_size)
46
+
47
+ if torchvision._is_tracing():
48
+ scale_factor = _fake_cast_onnx(scale)
49
+ else:
50
+ scale_factor = scale.item()
51
+ recompute_scale_factor = True
52
+
53
+ image = torch.nn.functional.interpolate(
54
+ image[None],
55
+ size=size,
56
+ scale_factor=scale_factor,
57
+ mode="bilinear",
58
+ recompute_scale_factor=recompute_scale_factor,
59
+ align_corners=False,
60
+ )[0]
61
+
62
+ if target is None:
63
+ return image, target
64
+
65
+ if "masks" in target:
66
+ mask = target["masks"]
67
+ mask = torch.nn.functional.interpolate(
68
+ mask[:, None].float(), size=size, scale_factor=scale_factor, recompute_scale_factor=recompute_scale_factor
69
+ )[:, 0].byte()
70
+ target["masks"] = mask
71
+ return image, target
72
+
73
+
74
+ class GeneralizedRCNNTransform(nn.Module):
75
+ """
76
+ Performs input / target transformation before feeding the data to a GeneralizedRCNN
77
+ model.
78
+
79
+ The transformations it perform are:
80
+ - input normalization (mean subtraction and std division)
81
+ - input / target resizing to match min_size / max_size
82
+
83
+ It returns a ImageList for the inputs, and a List[Dict[Tensor]] for the targets
84
+ """
85
+
86
+ def __init__(
87
+ self,
88
+ min_size: int,
89
+ max_size: int,
90
+ image_mean: List[float],
91
+ image_std: List[float],
92
+ size_divisible: int = 32,
93
+ fixed_size: Optional[Tuple[int, int]] = None,
94
+ **kwargs: Any,
95
+ ):
96
+ super().__init__()
97
+ if not isinstance(min_size, (list, tuple)):
98
+ min_size = (min_size,)
99
+ self.min_size = min_size
100
+ self.max_size = max_size
101
+ self.image_mean = image_mean
102
+ self.image_std = image_std
103
+ self.size_divisible = size_divisible
104
+ self.fixed_size = fixed_size
105
+ self._skip_resize = kwargs.pop("_skip_resize", False)
106
+
107
+ def forward(
108
+ self, images: List[Tensor], targets: Optional[List[Dict[str, Tensor]]] = None
109
+ ) -> Tuple[ImageList, Optional[List[Dict[str, Tensor]]]]:
110
+ images = [img for img in images]
111
+ if targets is not None:
112
+ # make a copy of targets to avoid modifying it in-place
113
+ # once torchscript supports dict comprehension
114
+ # this can be simplified as follows
115
+ # targets = [{k: v for k,v in t.items()} for t in targets]
116
+ targets_copy: List[Dict[str, Tensor]] = []
117
+ for t in targets:
118
+ data: Dict[str, Tensor] = {}
119
+ for k, v in t.items():
120
+ data[k] = v
121
+ targets_copy.append(data)
122
+ targets = targets_copy
123
+ for i in range(len(images)):
124
+ image = images[i]
125
+ target_index = targets[i] if targets is not None else None
126
+
127
+ if image.dim() != 3:
128
+ raise ValueError(f"images is expected to be a list of 3d tensors of shape [C, H, W], got {image.shape}")
129
+ image = self.normalize(image)
130
+ image, target_index = self.resize(image, target_index)
131
+ images[i] = image
132
+ if targets is not None and target_index is not None:
133
+ targets[i] = target_index
134
+
135
+ image_sizes = [img.shape[-2:] for img in images]
136
+ images = self.batch_images(images, size_divisible=self.size_divisible)
137
+ image_sizes_list: List[Tuple[int, int]] = []
138
+ for image_size in image_sizes:
139
+ torch._assert(
140
+ len(image_size) == 2,
141
+ f"Input tensors expected to have in the last two elements H and W, instead got {image_size}",
142
+ )
143
+ image_sizes_list.append((image_size[0], image_size[1]))
144
+
145
+ image_list = ImageList(images, image_sizes_list)
146
+ return image_list, targets
147
+
148
+ def normalize(self, image: Tensor) -> Tensor:
149
+ if not image.is_floating_point():
150
+ raise TypeError(
151
+ f"Expected input images to be of floating type (in range [0, 1]), "
152
+ f"but found type {image.dtype} instead"
153
+ )
154
+ dtype, device = image.dtype, image.device
155
+ mean = torch.as_tensor(self.image_mean, dtype=dtype, device=device)
156
+ std = torch.as_tensor(self.image_std, dtype=dtype, device=device)
157
+ return (image - mean[:, None, None]) / std[:, None, None]
158
+
159
+ def torch_choice(self, k: List[int]) -> int:
160
+ """
161
+ Implements `random.choice` via torch ops so it can be compiled with
162
+ TorchScript. Remove if https://github.com/pytorch/pytorch/issues/25803
163
+ is fixed.
164
+ """
165
+ index = int(torch.empty(1).uniform_(0.0, float(len(k))).item())
166
+ return k[index]
167
+
168
+ def resize(
169
+ self,
170
+ image: Tensor,
171
+ target: Optional[Dict[str, Tensor]] = None,
172
+ ) -> Tuple[Tensor, Optional[Dict[str, Tensor]]]:
173
+ h, w = image.shape[-2:]
174
+ if self.training:
175
+ if self._skip_resize:
176
+ return image, target
177
+ size = float(self.torch_choice(self.min_size))
178
+ else:
179
+ # FIXME assume for now that testing uses the largest scale
180
+ size = float(self.min_size[-1])
181
+ image, target = _resize_image_and_masks(image, size, float(self.max_size), target, self.fixed_size)
182
+
183
+ if target is None:
184
+ return image, target
185
+
186
+ bbox = target["boxes"]
187
+ bbox = resize_boxes(bbox, (h, w), image.shape[-2:])
188
+ target["boxes"] = bbox
189
+
190
+ if "keypoints" in target:
191
+ keypoints = target["keypoints"]
192
+ keypoints = resize_keypoints(keypoints, (h, w), image.shape[-2:])
193
+ target["keypoints"] = keypoints
194
+ return image, target
195
+
196
+ # _onnx_batch_images() is an implementation of
197
+ # batch_images() that is supported by ONNX tracing.
198
+ @torch.jit.unused
199
+ def _onnx_batch_images(self, images: List[Tensor], size_divisible: int = 32) -> Tensor:
200
+ max_size = []
201
+ for i in range(images[0].dim()):
202
+ max_size_i = torch.max(torch.stack([img.shape[i] for img in images]).to(torch.float32)).to(torch.int64)
203
+ max_size.append(max_size_i)
204
+ stride = size_divisible
205
+ max_size[1] = (torch.ceil((max_size[1].to(torch.float32)) / stride) * stride).to(torch.int64)
206
+ max_size[2] = (torch.ceil((max_size[2].to(torch.float32)) / stride) * stride).to(torch.int64)
207
+ max_size = tuple(max_size)
208
+
209
+ # work around for
210
+ # pad_img[: img.shape[0], : img.shape[1], : img.shape[2]].copy_(img)
211
+ # which is not yet supported in onnx
212
+ padded_imgs = []
213
+ for img in images:
214
+ padding = [(s1 - s2) for s1, s2 in zip(max_size, tuple(img.shape))]
215
+ padded_img = torch.nn.functional.pad(img, (0, padding[2], 0, padding[1], 0, padding[0]))
216
+ padded_imgs.append(padded_img)
217
+
218
+ return torch.stack(padded_imgs)
219
+
220
+ def max_by_axis(self, the_list: List[List[int]]) -> List[int]:
221
+ maxes = the_list[0]
222
+ for sublist in the_list[1:]:
223
+ for index, item in enumerate(sublist):
224
+ maxes[index] = max(maxes[index], item)
225
+ return maxes
226
+
227
+ def batch_images(self, images: List[Tensor], size_divisible: int = 32) -> Tensor:
228
+ if torchvision._is_tracing():
229
+ # batch_images() does not export well to ONNX
230
+ # call _onnx_batch_images() instead
231
+ return self._onnx_batch_images(images, size_divisible)
232
+
233
+ max_size = self.max_by_axis([list(img.shape) for img in images])
234
+ stride = float(size_divisible)
235
+ max_size = list(max_size)
236
+ max_size[1] = int(math.ceil(float(max_size[1]) / stride) * stride)
237
+ max_size[2] = int(math.ceil(float(max_size[2]) / stride) * stride)
238
+
239
+ batch_shape = [len(images)] + max_size
240
+ batched_imgs = images[0].new_full(batch_shape, 0)
241
+ for i in range(batched_imgs.shape[0]):
242
+ img = images[i]
243
+ batched_imgs[i, : img.shape[0], : img.shape[1], : img.shape[2]].copy_(img)
244
+
245
+ return batched_imgs
246
+
247
+ def postprocess(
248
+ self,
249
+ result: List[Dict[str, Tensor]],
250
+ image_shapes: List[Tuple[int, int]],
251
+ original_image_sizes: List[Tuple[int, int]],
252
+ ) -> List[Dict[str, Tensor]]:
253
+ if self.training:
254
+ return result
255
+ for i, (pred, im_s, o_im_s) in enumerate(zip(result, image_shapes, original_image_sizes)):
256
+ boxes = pred["boxes"]
257
+ boxes = resize_boxes(boxes, im_s, o_im_s)
258
+ result[i]["boxes"] = boxes
259
+ if "masks" in pred:
260
+ masks = pred["masks"]
261
+ masks = paste_masks_in_image(masks, boxes, o_im_s)
262
+ result[i]["masks"] = masks
263
+ if "keypoints" in pred:
264
+ keypoints = pred["keypoints"]
265
+ keypoints = resize_keypoints(keypoints, im_s, o_im_s)
266
+ result[i]["keypoints"] = keypoints
267
+ return result
268
+
269
+ def __repr__(self) -> str:
270
+ format_string = f"{self.__class__.__name__}("
271
+ _indent = "\n "
272
+ format_string += f"{_indent}Normalize(mean={self.image_mean}, std={self.image_std})"
273
+ format_string += f"{_indent}Resize(min_size={self.min_size}, max_size={self.max_size}, mode='bilinear')"
274
+ format_string += "\n)"
275
+ return format_string
276
+
277
+
278
+ def resize_keypoints(keypoints: Tensor, original_size: List[int], new_size: List[int]) -> Tensor:
279
+ ratios = [
280
+ torch.tensor(s, dtype=torch.float32, device=keypoints.device)
281
+ / torch.tensor(s_orig, dtype=torch.float32, device=keypoints.device)
282
+ for s, s_orig in zip(new_size, original_size)
283
+ ]
284
+ ratio_h, ratio_w = ratios
285
+ resized_data = keypoints.clone()
286
+ if torch._C._get_tracing_state():
287
+ resized_data_0 = resized_data[:, :, 0] * ratio_w
288
+ resized_data_1 = resized_data[:, :, 1] * ratio_h
289
+ resized_data = torch.stack((resized_data_0, resized_data_1, resized_data[:, :, 2]), dim=2)
290
+ else:
291
+ resized_data[..., 0] *= ratio_w
292
+ resized_data[..., 1] *= ratio_h
293
+ return resized_data
294
+
295
+
296
+ def resize_boxes(boxes: Tensor, original_size: List[int], new_size: List[int]) -> Tensor:
297
+ ratios = [
298
+ torch.tensor(s, dtype=torch.float32, device=boxes.device)
299
+ / torch.tensor(s_orig, dtype=torch.float32, device=boxes.device)
300
+ for s, s_orig in zip(new_size, original_size)
301
+ ]
302
+ ratio_height, ratio_width = ratios
303
+ xmin, ymin, xmax, ymax = boxes.unbind(1)
304
+
305
+ xmin = xmin * ratio_width
306
+ xmax = xmax * ratio_width
307
+ ymin = ymin * ratio_height
308
+ ymax = ymax * ratio_height
309
+ return torch.stack((xmin, ymin, xmax, ymax), dim=1)
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/optical_flow/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (204 Bytes). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/optical_flow/__pycache__/_utils.cpython-38.pyc ADDED
Binary file (2.04 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/optical_flow/__pycache__/raft.cpython-38.pyc ADDED
Binary file (27 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (293 Bytes). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/googlenet.cpython-38.pyc ADDED
Binary file (8.06 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/inception.cpython-38.pyc ADDED
Binary file (10.8 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/mobilenet.cpython-38.pyc ADDED
Binary file (307 Bytes). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/mobilenetv2.cpython-38.pyc ADDED
Binary file (6.25 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/quantization/__pycache__/mobilenetv3.cpython-38.pyc ADDED
Binary file (8.53 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (242 Bytes). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/_utils.cpython-38.pyc ADDED
Binary file (1.44 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/deeplabv3.cpython-38.pyc ADDED
Binary file (12.4 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/fcn.cpython-38.pyc ADDED
Binary file (7.79 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/lraspp.cpython-38.pyc ADDED
Binary file (7.26 kB). View file
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/torchvision/models/segmentation/__pycache__/segmentation.cpython-38.pyc ADDED
Binary file (431 Bytes). View file