增加构建脚本
This commit is contained in:
parent
f9b3c2397b
commit
609c58e8e7
55
Dockerfile
55
Dockerfile
|
|
@ -1,53 +1,6 @@
|
|||
## 第一阶段:构建阶段
|
||||
#FROM python:3.11-slim-bullseye AS builder
|
||||
#
|
||||
## 配置APT清华源
|
||||
#RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list \
|
||||
# && sed -i 's/security.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list
|
||||
#
|
||||
## 安装基础系统依赖
|
||||
#RUN apt-get update && apt-get install -y \
|
||||
# build-essential \
|
||||
# libssl-dev \
|
||||
# zlib1g-dev \
|
||||
# libffi-dev \
|
||||
# libgl1 \
|
||||
# ffmpeg \
|
||||
# && rm -rf /var/lib/apt/lists/*
|
||||
#
|
||||
## 创建虚拟环境
|
||||
#RUN python -m venv /opt/venv
|
||||
#ENV PATH="/opt/venv/bin:$PATH"
|
||||
FROM 172.20.32.187/machine-learning/video:v1
|
||||
LABEL authors="zch"
|
||||
|
||||
COPY app.py cache /app/
|
||||
|
||||
|
||||
|
||||
FROM python_3_11:hnxjy
|
||||
# 配置清华源加速
|
||||
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple \
|
||||
&& pip config set install.trusted-host pypi.tuna.tsinghua.edu.cn
|
||||
|
||||
# 安装Python依赖(利用分层缓存)
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# 安装最小化运行时依赖
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libgl1 \
|
||||
ffmpeg \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 设置容器环境
|
||||
COPY . .
|
||||
|
||||
# 配置Python优化参数
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONPATH=/app \
|
||||
LANG=C.UTF-8
|
||||
|
||||
# 暴露应用端口
|
||||
EXPOSE 7860
|
||||
|
||||
# 启动命令
|
||||
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
||||
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "1888"]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
## 第一阶段:构建阶段
|
||||
#FROM python:3.11-slim-bullseye AS builder
|
||||
#
|
||||
## 配置APT清华源
|
||||
#RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list \
|
||||
# && sed -i 's/security.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list
|
||||
#
|
||||
## 安装基础系统依赖
|
||||
#RUN apt-get update && apt-get install -y \
|
||||
# build-essential \
|
||||
# libssl-dev \
|
||||
# zlib1g-dev \
|
||||
# libffi-dev \
|
||||
# libgl1 \
|
||||
# ffmpeg \
|
||||
# && rm -rf /var/lib/apt/lists/*
|
||||
#
|
||||
## 创建虚拟环境
|
||||
#RUN python -m venv /opt/venv
|
||||
#ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
|
||||
|
||||
|
||||
FROM python_3_11:hnxjy
|
||||
# 配置清华源加速
|
||||
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple \
|
||||
&& pip config set install.trusted-host pypi.tuna.tsinghua.edu.cn
|
||||
|
||||
# 安装Python依赖(利用分层缓存)
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# 安装最小化运行时依赖
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libgl1 \
|
||||
ffmpeg \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 设置容器环境
|
||||
COPY . .
|
||||
|
||||
# 配置Python优化参数
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONPATH=/app \
|
||||
LANG=C.UTF-8
|
||||
|
||||
# 暴露应用端口
|
||||
EXPOSE 7860
|
||||
|
||||
# 启动命令
|
||||
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
tag=$(date +%Y%m%d%H%M%S)
|
||||
|
||||
image=172.20.32.187/machine-learning/video:${tag}
|
||||
docker build -t ${image} .
|
||||
|
||||
docker push $image
|
||||
Binary file not shown.
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlinesLeft: true
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
#CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, ]
|
||||
IncludeCategories:
|
||||
- Regex: '^<.*\.h(pp)?>'
|
||||
Priority: 1
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
IndentCaseLabels: true
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 2000000
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
---
|
||||
Language: ObjC
|
||||
ColumnLimit: 120
|
||||
AlignAfterOpenBracket: Align
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
...
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# This file keeps git blame clean.
|
||||
# See https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignore-commits-in-the-blame-view
|
||||
|
||||
# Add ufmt (usort + black) as code formatter (#4384)
|
||||
5f0edb97b46e5bff71dc19dedef05c5396eeaea2
|
||||
# update python syntax >=3.6 (#4585)
|
||||
d367a01a18a3ae6bee13d8be3b63fd6a581ea46f
|
||||
# Upgrade usort to 1.0.2 and black to 22.3.0 (#5106)
|
||||
6ca9c76adb6daf2695d603ad623a9cf1c4f4806f
|
||||
# Fix unnecessary exploded black formatting (#7709)
|
||||
a335d916db0694770e8152f41e19195de3134523
|
||||
# Renaming: `BoundingBox` -> `BoundingBoxes` (#7778)
|
||||
332bff937c6711666191880fab57fa2f23ae772e
|
||||
# Upgrade type hint and others to Python 3.9 (#8814)
|
||||
a095de183d3811d79ed0db2715e7a1c3162fa19d
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
*.pkl binary
|
||||
# Jupyter notebook
|
||||
|
||||
# For text count
|
||||
# *.ipynb text
|
||||
|
||||
# To ignore it use below
|
||||
*.ipynb linguist-documentation
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
name: 🐛 Bug Report
|
||||
description: Create a report to help us reproduce and fix the bug
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
#### Before submitting a bug, please make sure the issue hasn't been already addressed by searching through [the existing and past issues](https://github.com/pytorch/vision/issues?q=is%3Aissue+sort%3Acreated-desc+).
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 🐛 Describe the bug
|
||||
description: |
|
||||
Please provide a clear and concise description of what the bug is.
|
||||
|
||||
If relevant, add a minimal example so that we can reproduce the error by running the code. It is very important for the snippet to be as succinct (minimal) as possible, so please take time to trim down any irrelevant code to help us debug efficiently. We are going to copy-paste your code and we expect to get the same result as you did: avoid any external data, and include the relevant imports, etc. For example:
|
||||
|
||||
```python
|
||||
# All necessary imports at the beginning
|
||||
import torch
|
||||
import torchvision
|
||||
from torchvision.ops import nms
|
||||
|
||||
# A succinct reproducing example trimmed down to the essential parts:
|
||||
N = 5
|
||||
boxes = torch.rand(N, 4) # Note: the bug is here, we should enforce that x1 < x2 and y1 < y2!
|
||||
scores = torch.rand(N)
|
||||
nms(boxes, scores, iou_threshold=.9)
|
||||
```
|
||||
|
||||
If the code is too long (hopefully, it isn't), feel free to put it in a public gist and link it in the issue: https://gist.github.com.
|
||||
|
||||
Please also paste or describe the results you observe instead of the expected results. If you observe an error, please paste the error message including the **full** traceback of the exception. It may be relevant to wrap error messages in ```` ```triple quotes blocks``` ````.
|
||||
placeholder: |
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
```python
|
||||
Sample code to reproduce the problem
|
||||
```
|
||||
|
||||
```
|
||||
The error message you got, with the full traceback.
|
||||
````
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Versions
|
||||
description: |
|
||||
Please run the following and paste the output below.
|
||||
```sh
|
||||
wget https://raw.githubusercontent.com/pytorch/pytorch/main/torch/utils/collect_env.py
|
||||
# For security purposes, please check the contents of collect_env.py before running it.
|
||||
python collect_env.py
|
||||
```
|
||||
validations:
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
Thanks for contributing 🎉!
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Usage questions
|
||||
url: https://discuss.pytorch.org/
|
||||
about: Ask questions and discuss with other torchvision community members
|
||||
20
cache/torch/hub/pytorch_vision_main/.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
20
cache/torch/hub/pytorch_vision_main/.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
name: 📚 Documentation
|
||||
description: Report an issue related to https://pytorch.org/vision/stable/index.html
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 📚 The doc issue
|
||||
description: >
|
||||
A clear and concise description of what content in https://pytorch.org/vision/stable/index.html is an issue. If this has to do with the general https://pytorch.org website, please file an issue at https://github.com/pytorch/pytorch.github.io/issues/new/choose instead. If this has to do with https://pytorch.org/tutorials, please file an issue at https://github.com/pytorch/tutorials/issues/new.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Suggest a potential alternative/fix
|
||||
description: >
|
||||
Tell us how we could improve the documentation in this regard.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
Thanks for contributing 🎉!
|
||||
32
cache/torch/hub/pytorch_vision_main/.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
32
cache/torch/hub/pytorch_vision_main/.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
name: 🚀 Feature request
|
||||
description: Submit a proposal/request for a new torchvision feature
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 🚀 The feature
|
||||
description: >
|
||||
A clear and concise description of the feature proposal
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Motivation, pitch
|
||||
description: >
|
||||
Please outline the motivation for the proposal. Is your feature request related to a specific problem? e.g., *"I'm working on X and would like Y to be possible"*. If this is related to another GitHub issue, please link here too.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Alternatives
|
||||
description: >
|
||||
A description of any alternative solutions or features you've considered, if any.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: >
|
||||
Add any other context or screenshots about the feature request.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
Thanks for contributing 🎉!
|
||||
|
|
@ -0,0 +1 @@
|
|||
<!-- Before submitting a PR, please make sure to check our contributing guidelines regarding code formatting, tests, and documentation: https://github.com/pytorch/vision/blob/main/CONTRIBUTING.md -->
|
||||
13
cache/torch/hub/pytorch_vision_main/.github/failed_schedule_issue_template.md
vendored
Normal file
13
cache/torch/hub/pytorch_vision_main/.github/failed_schedule_issue_template.md
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
title: Scheduled workflow failed
|
||||
labels:
|
||||
- bug
|
||||
- "module: datasets"
|
||||
---
|
||||
|
||||
Oh no, something went wrong in the scheduled workflow {{ env.WORKFLOW }}/{{ env.JOB }}.
|
||||
Please look into it:
|
||||
|
||||
https://github.com/{{ env.REPO }}/actions/runs/{{ env.ID }}
|
||||
|
||||
Feel free to close this if this was just a one-off error.
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
"""
|
||||
This script finds the merger responsible for labeling a PR by a commit SHA. It is used by the workflow in
|
||||
'.github/workflows/pr-labels.yml'. If there exists no PR associated with the commit or the PR is properly labeled,
|
||||
this script is a no-op.
|
||||
|
||||
Note: we ping the merger only, not the reviewers, as the reviewers can sometimes be external to torchvision
|
||||
with no labeling responsibility, so we don't want to bother them.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from typing import Any, Optional, Set, Tuple
|
||||
|
||||
import requests
|
||||
|
||||
# For a PR to be properly labeled it should have one primary label and one secondary label
|
||||
PRIMARY_LABELS = {
|
||||
"new feature",
|
||||
"bug",
|
||||
"code quality",
|
||||
"enhancement",
|
||||
"bc-breaking",
|
||||
"deprecation",
|
||||
"other",
|
||||
"prototype",
|
||||
}
|
||||
|
||||
SECONDARY_LABELS = {
|
||||
"dependency issue",
|
||||
"module: c++ frontend",
|
||||
"module: ci",
|
||||
"module: datasets",
|
||||
"module: documentation",
|
||||
"module: io",
|
||||
"module: models.quantization",
|
||||
"module: models",
|
||||
"module: onnx",
|
||||
"module: ops",
|
||||
"module: reference scripts",
|
||||
"module: rocm",
|
||||
"module: tests",
|
||||
"module: transforms",
|
||||
"module: utils",
|
||||
"module: video",
|
||||
"Perf",
|
||||
"Revert(ed)",
|
||||
"topic: build",
|
||||
}
|
||||
|
||||
|
||||
def query_torchvision(cmd: str, *, accept) -> Any:
|
||||
response = requests.get(f"https://api.github.com/repos/pytorch/vision/{cmd}", headers=dict(Accept=accept))
|
||||
return response.json()
|
||||
|
||||
|
||||
def get_pr_number(commit_hash: str) -> Optional[int]:
|
||||
# See https://docs.github.com/en/rest/reference/repos#list-pull-requests-associated-with-a-commit
|
||||
data = query_torchvision(f"commits/{commit_hash}/pulls", accept="application/vnd.github.groot-preview+json")
|
||||
if not data:
|
||||
return None
|
||||
return data[0]["number"]
|
||||
|
||||
|
||||
def get_pr_merger_and_labels(pr_number: int) -> Tuple[str, Set[str]]:
|
||||
# See https://docs.github.com/en/rest/reference/pulls#get-a-pull-request
|
||||
data = query_torchvision(f"pulls/{pr_number}", accept="application/vnd.github.v3+json")
|
||||
merger = data["merged_by"]["login"]
|
||||
labels = {label["name"] for label in data["labels"]}
|
||||
return merger, labels
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
commit_hash = sys.argv[1]
|
||||
pr_number = get_pr_number(commit_hash)
|
||||
if not pr_number:
|
||||
sys.exit(0)
|
||||
|
||||
merger, labels = get_pr_merger_and_labels(pr_number)
|
||||
is_properly_labeled = bool(PRIMARY_LABELS.intersection(labels) and SECONDARY_LABELS.intersection(labels))
|
||||
|
||||
if not is_properly_labeled:
|
||||
print(f"@{merger}")
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
tracking_issue: 2447
|
||||
|
||||
# List of workflows that will be re-run in case of failures
|
||||
# https://github.com/pytorch/test-infra/blob/main/torchci/lib/bot/retryBot.ts
|
||||
retryable_workflows:
|
||||
- Build Linux
|
||||
- Build Macos
|
||||
- Build M1
|
||||
- Build Windows
|
||||
- Tests
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
./.github/scripts/setup-env.sh
|
||||
|
||||
# Activate conda environment
|
||||
set +x && eval "$($(which conda) shell.bash hook)" && conda deactivate && conda activate ci && set -x
|
||||
|
||||
# Setup the OS_TYPE environment variable that should be used for conditions involving the OS below.
|
||||
case $(uname) in
|
||||
Linux)
|
||||
OS_TYPE=linux
|
||||
;;
|
||||
Darwin)
|
||||
OS_TYPE=macos
|
||||
;;
|
||||
MSYS*)
|
||||
OS_TYPE=windows
|
||||
;;
|
||||
*)
|
||||
echo "Unknown OS type:" $(uname)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ $OS_TYPE == macos ]]; then
|
||||
JOBS=$(sysctl -n hw.logicalcpu)
|
||||
else
|
||||
JOBS=$(nproc)
|
||||
fi
|
||||
|
||||
if [[ $OS_TYPE == linux ]]; then
|
||||
export LD_LIBRARY_PATH="${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH}"
|
||||
fi
|
||||
|
||||
TORCH_PATH=$(python -c "import pathlib, torch; print(pathlib.Path(torch.__path__[0]))")
|
||||
if [[ $OS_TYPE == windows ]]; then
|
||||
PACKAGING_DIR="${PWD}/packaging"
|
||||
export PATH="${TORCH_PATH}/lib:${PATH}"
|
||||
fi
|
||||
|
||||
Torch_DIR="${TORCH_PATH}/share/cmake/Torch"
|
||||
if [[ "${GPU_ARCH_TYPE}" == "cuda" ]]; then
|
||||
WITH_CUDA=1
|
||||
else
|
||||
WITH_CUDA=0
|
||||
fi
|
||||
|
||||
echo '::group::Prepare CMake builds'
|
||||
mkdir -p cpp_build
|
||||
|
||||
pushd examples/cpp
|
||||
python script_model.py
|
||||
mkdir -p build
|
||||
mv resnet18.pt fasterrcnn_resnet50_fpn.pt build
|
||||
popd
|
||||
|
||||
# This was only needed for the tracing above
|
||||
pip uninstall -y torchvision
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::Build and install libtorchvision'
|
||||
pushd cpp_build
|
||||
|
||||
|
||||
# On macOS, CMake is looking for the library (*.dylib) and the header (*.h) separately. By default, it prefers to load
|
||||
# the header from other packages that install the library. This easily leads to a mismatch if the library installed
|
||||
# from conda doesn't have the exact same version. Thus, we need to explicitly set CMAKE_FIND_FRAMEWORK=NEVER to force
|
||||
# it to not load anything from other installed frameworks. Resources:
|
||||
# https://stackoverflow.com/questions/36523911/osx-homebrew-cmake-libpng-version-mismatch-issue
|
||||
# https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_FRAMEWORK.html
|
||||
cmake .. -DTorch_DIR="${Torch_DIR}" -DWITH_CUDA="${WITH_CUDA}" \
|
||||
-DCMAKE_PREFIX_PATH="${CONDA_PREFIX}" \
|
||||
-DCMAKE_FIND_FRAMEWORK=NEVER \
|
||||
-DCMAKE_INSTALL_PREFIX="${CONDA_PREFIX}"
|
||||
if [[ $OS_TYPE == windows ]]; then
|
||||
"${PACKAGING_DIR}/windows/internal/vc_env_helper.bat" "${PACKAGING_DIR}/windows/internal/build_cmake.bat" $JOBS
|
||||
else
|
||||
make -j$JOBS
|
||||
make install
|
||||
fi
|
||||
|
||||
popd
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::Build and run C++ example'
|
||||
pushd examples/cpp/build
|
||||
|
||||
cmake .. -DTorch_DIR="${Torch_DIR}" \
|
||||
-DCMAKE_PREFIX_PATH="${CONDA_PREFIX}" \
|
||||
-DCMAKE_FIND_FRAMEWORK=NEVER \
|
||||
-DUSE_TORCHVISION=ON # Needed for faster-rcnn since it's using torchvision ops like NMS.
|
||||
if [[ $OS_TYPE == windows ]]; then
|
||||
"${PACKAGING_DIR}/windows/internal/vc_env_helper.bat" "${PACKAGING_DIR}/windows/internal/build_cpp_example.bat" $JOBS
|
||||
cd Release
|
||||
cp ../resnet18.pt .
|
||||
cp ../fasterrcnn_resnet50_fpn.pt .
|
||||
else
|
||||
make -j$JOBS
|
||||
fi
|
||||
|
||||
./run_model resnet18.pt
|
||||
./run_model fasterrcnn_resnet50_fpn.pt
|
||||
|
||||
popd
|
||||
echo '::endgroup::'
|
||||
3
cache/torch/hub/pytorch_vision_main/.github/scripts/export_IS_M1_CONDA_BUILD_JOB.sh
vendored
Normal file
3
cache/torch/hub/pytorch_vision_main/.github/scripts/export_IS_M1_CONDA_BUILD_JOB.sh
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
export IS_M1_CONDA_BUILD_JOB=1
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Guillaume Papin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
A wrapper script around clang-format, suitable for linting multiple files
|
||||
and to use for continuous integration.
|
||||
|
||||
This is an alternative API for the clang-format command line.
|
||||
It runs over multiple files and directories in parallel.
|
||||
A diff output is produced and a sensible exit code is returned.
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import difflib
|
||||
import fnmatch
|
||||
import multiprocessing
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import traceback
|
||||
from functools import partial
|
||||
|
||||
try:
|
||||
from subprocess import DEVNULL # py3k
|
||||
except ImportError:
|
||||
DEVNULL = open(os.devnull, "wb")
|
||||
|
||||
|
||||
DEFAULT_EXTENSIONS = "c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx,cu,mm"
|
||||
|
||||
|
||||
class ExitStatus:
|
||||
SUCCESS = 0
|
||||
DIFF = 1
|
||||
TROUBLE = 2
|
||||
|
||||
|
||||
def list_files(files, recursive=False, extensions=None, exclude=None):
|
||||
if extensions is None:
|
||||
extensions = []
|
||||
if exclude is None:
|
||||
exclude = []
|
||||
|
||||
out = []
|
||||
for file in files:
|
||||
if recursive and os.path.isdir(file):
|
||||
for dirpath, dnames, fnames in os.walk(file):
|
||||
fpaths = [os.path.join(dirpath, fname) for fname in fnames]
|
||||
for pattern in exclude:
|
||||
# os.walk() supports trimming down the dnames list
|
||||
# by modifying it in-place,
|
||||
# to avoid unnecessary directory listings.
|
||||
dnames[:] = [x for x in dnames if not fnmatch.fnmatch(os.path.join(dirpath, x), pattern)]
|
||||
fpaths = [x for x in fpaths if not fnmatch.fnmatch(x, pattern)]
|
||||
for f in fpaths:
|
||||
ext = os.path.splitext(f)[1][1:]
|
||||
if ext in extensions:
|
||||
out.append(f)
|
||||
else:
|
||||
out.append(file)
|
||||
return out
|
||||
|
||||
|
||||
def make_diff(file, original, reformatted):
|
||||
return list(
|
||||
difflib.unified_diff(
|
||||
original, reformatted, fromfile=f"{file}\t(original)", tofile=f"{file}\t(reformatted)", n=3
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class DiffError(Exception):
|
||||
def __init__(self, message, errs=None):
|
||||
super().__init__(message)
|
||||
self.errs = errs or []
|
||||
|
||||
|
||||
class UnexpectedError(Exception):
|
||||
def __init__(self, message, exc=None):
|
||||
super().__init__(message)
|
||||
self.formatted_traceback = traceback.format_exc()
|
||||
self.exc = exc
|
||||
|
||||
|
||||
def run_clang_format_diff_wrapper(args, file):
|
||||
try:
|
||||
ret = run_clang_format_diff(args, file)
|
||||
return ret
|
||||
except DiffError:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise UnexpectedError(f"{file}: {e.__class__.__name__}: {e}", e)
|
||||
|
||||
|
||||
def run_clang_format_diff(args, file):
|
||||
try:
|
||||
with open(file, encoding="utf-8") as f:
|
||||
original = f.readlines()
|
||||
except OSError as exc:
|
||||
raise DiffError(str(exc))
|
||||
invocation = [args.clang_format_executable, file]
|
||||
|
||||
# Use of utf-8 to decode the process output.
|
||||
#
|
||||
# Hopefully, this is the correct thing to do.
|
||||
#
|
||||
# It's done due to the following assumptions (which may be incorrect):
|
||||
# - clang-format will returns the bytes read from the files as-is,
|
||||
# without conversion, and it is already assumed that the files use utf-8.
|
||||
# - if the diagnostics were internationalized, they would use utf-8:
|
||||
# > Adding Translations to Clang
|
||||
# >
|
||||
# > Not possible yet!
|
||||
# > Diagnostic strings should be written in UTF-8,
|
||||
# > the client can translate to the relevant code page if needed.
|
||||
# > Each translation completely replaces the format string
|
||||
# > for the diagnostic.
|
||||
# > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation
|
||||
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
invocation, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, encoding="utf-8"
|
||||
)
|
||||
except OSError as exc:
|
||||
raise DiffError(f"Command '{subprocess.list2cmdline(invocation)}' failed to start: {exc}")
|
||||
proc_stdout = proc.stdout
|
||||
proc_stderr = proc.stderr
|
||||
|
||||
# hopefully the stderr pipe won't get full and block the process
|
||||
outs = list(proc_stdout.readlines())
|
||||
errs = list(proc_stderr.readlines())
|
||||
proc.wait()
|
||||
if proc.returncode:
|
||||
raise DiffError(
|
||||
"Command '{}' returned non-zero exit status {}".format(
|
||||
subprocess.list2cmdline(invocation), proc.returncode
|
||||
),
|
||||
errs,
|
||||
)
|
||||
return make_diff(file, original, outs), errs
|
||||
|
||||
|
||||
def bold_red(s):
|
||||
return "\x1b[1m\x1b[31m" + s + "\x1b[0m"
|
||||
|
||||
|
||||
def colorize(diff_lines):
|
||||
def bold(s):
|
||||
return "\x1b[1m" + s + "\x1b[0m"
|
||||
|
||||
def cyan(s):
|
||||
return "\x1b[36m" + s + "\x1b[0m"
|
||||
|
||||
def green(s):
|
||||
return "\x1b[32m" + s + "\x1b[0m"
|
||||
|
||||
def red(s):
|
||||
return "\x1b[31m" + s + "\x1b[0m"
|
||||
|
||||
for line in diff_lines:
|
||||
if line[:4] in ["--- ", "+++ "]:
|
||||
yield bold(line)
|
||||
elif line.startswith("@@ "):
|
||||
yield cyan(line)
|
||||
elif line.startswith("+"):
|
||||
yield green(line)
|
||||
elif line.startswith("-"):
|
||||
yield red(line)
|
||||
else:
|
||||
yield line
|
||||
|
||||
|
||||
def print_diff(diff_lines, use_color):
|
||||
if use_color:
|
||||
diff_lines = colorize(diff_lines)
|
||||
sys.stdout.writelines(diff_lines)
|
||||
|
||||
|
||||
def print_trouble(prog, message, use_colors):
|
||||
error_text = "error:"
|
||||
if use_colors:
|
||||
error_text = bold_red(error_text)
|
||||
print(f"{prog}: {error_text} {message}", file=sys.stderr)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument(
|
||||
"--clang-format-executable",
|
||||
metavar="EXECUTABLE",
|
||||
help="path to the clang-format executable",
|
||||
default="clang-format",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--extensions",
|
||||
help=f"comma separated list of file extensions (default: {DEFAULT_EXTENSIONS})",
|
||||
default=DEFAULT_EXTENSIONS,
|
||||
)
|
||||
parser.add_argument("-r", "--recursive", action="store_true", help="run recursively over directories")
|
||||
parser.add_argument("files", metavar="file", nargs="+")
|
||||
parser.add_argument("-q", "--quiet", action="store_true")
|
||||
parser.add_argument(
|
||||
"-j",
|
||||
metavar="N",
|
||||
type=int,
|
||||
default=0,
|
||||
help="run N clang-format jobs in parallel (default number of cpus + 1)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--color", default="auto", choices=["auto", "always", "never"], help="show colored diff (default: auto)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-e",
|
||||
"--exclude",
|
||||
metavar="PATTERN",
|
||||
action="append",
|
||||
default=[],
|
||||
help="exclude paths matching the given glob-like pattern(s) from recursive search",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# use default signal handling, like diff return SIGINT value on ^C
|
||||
# https://bugs.python.org/issue14229#msg156446
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
try:
|
||||
signal.SIGPIPE
|
||||
except AttributeError:
|
||||
# compatibility, SIGPIPE does not exist on Windows
|
||||
pass
|
||||
else:
|
||||
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
||||
|
||||
colored_stdout = False
|
||||
colored_stderr = False
|
||||
if args.color == "always":
|
||||
colored_stdout = True
|
||||
colored_stderr = True
|
||||
elif args.color == "auto":
|
||||
colored_stdout = sys.stdout.isatty()
|
||||
colored_stderr = sys.stderr.isatty()
|
||||
|
||||
version_invocation = [args.clang_format_executable, "--version"]
|
||||
try:
|
||||
subprocess.check_call(version_invocation, stdout=DEVNULL)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print_trouble(parser.prog, str(e), use_colors=colored_stderr)
|
||||
return ExitStatus.TROUBLE
|
||||
except OSError as e:
|
||||
print_trouble(
|
||||
parser.prog,
|
||||
f"Command '{subprocess.list2cmdline(version_invocation)}' failed to start: {e}",
|
||||
use_colors=colored_stderr,
|
||||
)
|
||||
return ExitStatus.TROUBLE
|
||||
|
||||
retcode = ExitStatus.SUCCESS
|
||||
files = list_files(
|
||||
args.files, recursive=args.recursive, exclude=args.exclude, extensions=args.extensions.split(",")
|
||||
)
|
||||
|
||||
if not files:
|
||||
return
|
||||
|
||||
njobs = args.j
|
||||
if njobs == 0:
|
||||
njobs = multiprocessing.cpu_count() + 1
|
||||
njobs = min(len(files), njobs)
|
||||
|
||||
if njobs == 1:
|
||||
# execute directly instead of in a pool,
|
||||
# less overhead, simpler stacktraces
|
||||
it = (run_clang_format_diff_wrapper(args, file) for file in files)
|
||||
pool = None
|
||||
else:
|
||||
pool = multiprocessing.Pool(njobs)
|
||||
it = pool.imap_unordered(partial(run_clang_format_diff_wrapper, args), files)
|
||||
while True:
|
||||
try:
|
||||
outs, errs = next(it)
|
||||
except StopIteration:
|
||||
break
|
||||
except DiffError as e:
|
||||
print_trouble(parser.prog, str(e), use_colors=colored_stderr)
|
||||
retcode = ExitStatus.TROUBLE
|
||||
sys.stderr.writelines(e.errs)
|
||||
except UnexpectedError as e:
|
||||
print_trouble(parser.prog, str(e), use_colors=colored_stderr)
|
||||
sys.stderr.write(e.formatted_traceback)
|
||||
retcode = ExitStatus.TROUBLE
|
||||
# stop at the first unexpected error,
|
||||
# something could be very wrong,
|
||||
# don't process all files unnecessarily
|
||||
if pool:
|
||||
pool.terminate()
|
||||
break
|
||||
else:
|
||||
sys.stderr.writelines(errs)
|
||||
if outs == []:
|
||||
continue
|
||||
if not args.quiet:
|
||||
print_diff(outs, use_color=colored_stdout)
|
||||
if retcode == ExitStatus.SUCCESS:
|
||||
retcode = ExitStatus.DIFF
|
||||
return retcode
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
# Prepare conda
|
||||
set +x && eval "$($(which conda) shell.bash hook)" && set -x
|
||||
|
||||
# Setup the OS_TYPE environment variable that should be used for conditions involving the OS below.
|
||||
case $(uname) in
|
||||
Linux)
|
||||
OS_TYPE=linux
|
||||
;;
|
||||
Darwin)
|
||||
OS_TYPE=macos
|
||||
;;
|
||||
MSYS*)
|
||||
OS_TYPE=windows
|
||||
;;
|
||||
*)
|
||||
echo "Unknown OS type:" $(uname)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo '::group::Create build environment'
|
||||
# See https://github.com/pytorch/vision/issues/7296 for ffmpeg
|
||||
conda create \
|
||||
--name ci \
|
||||
--quiet --yes \
|
||||
python="${PYTHON_VERSION}" pip \
|
||||
ninja cmake \
|
||||
libpng \
|
||||
libwebp \
|
||||
'ffmpeg<4.3'
|
||||
conda activate ci
|
||||
conda install --quiet --yes libjpeg-turbo -c pytorch
|
||||
pip install --progress-bar=off --upgrade setuptools==72.1.0
|
||||
|
||||
# See https://github.com/pytorch/vision/issues/6790
|
||||
if [[ "${PYTHON_VERSION}" != "3.11" ]]; then
|
||||
pip install --progress-bar=off av!=10.0.0
|
||||
fi
|
||||
|
||||
echo '::endgroup::'
|
||||
|
||||
if [[ "${OS_TYPE}" == windows && "${GPU_ARCH_TYPE}" == cuda ]]; then
|
||||
echo '::group::Install VisualStudio CUDA extensions on Windows'
|
||||
TARGET_DIR="/c/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/MSBuild/Microsoft/VC/v170/BuildCustomizations"
|
||||
mkdir -p "${TARGET_DIR}"
|
||||
cp -r "${CUDA_HOME}/MSBuildExtensions/"* "${TARGET_DIR}"
|
||||
echo '::endgroup::'
|
||||
fi
|
||||
|
||||
echo '::group::Install PyTorch'
|
||||
# TODO: Can we maybe have this as environment variable in the job template? For example, `IS_RELEASE`.
|
||||
if [[ (${GITHUB_EVENT_NAME} = 'pull_request' && (${GITHUB_BASE_REF} = 'release'*)) || (${GITHUB_REF} = 'refs/heads/release'*) ]]; then
|
||||
CHANNEL=test
|
||||
else
|
||||
CHANNEL=nightly
|
||||
fi
|
||||
|
||||
case $GPU_ARCH_TYPE in
|
||||
cpu)
|
||||
GPU_ARCH_ID="cpu"
|
||||
;;
|
||||
cuda)
|
||||
VERSION_WITHOUT_DOT=$(echo "${GPU_ARCH_VERSION}" | sed 's/\.//')
|
||||
GPU_ARCH_ID="cu${VERSION_WITHOUT_DOT}"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown GPU_ARCH_TYPE=${GPU_ARCH_TYPE}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
PYTORCH_WHEEL_INDEX="https://download.pytorch.org/whl/${CHANNEL}/${GPU_ARCH_ID}"
|
||||
pip install --progress-bar=off --pre torch --index-url="${PYTORCH_WHEEL_INDEX}"
|
||||
|
||||
if [[ $GPU_ARCH_TYPE == 'cuda' ]]; then
|
||||
python -c "import torch; exit(not torch.cuda.is_available())"
|
||||
fi
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::Install third party dependencies prior to TorchVision install'
|
||||
# Installing with `easy_install`, e.g. `python setup.py install` or `python setup.py develop`, has some quirks when
|
||||
# when pulling in third-party dependencies. For example:
|
||||
# - On Windows, we often hit an SSL error although `pip` can install just fine.
|
||||
# - It happily pulls in pre-releases, which can lead to more problems down the line.
|
||||
# `pip` does not unless explicitly told to do so.
|
||||
# Thus, we use `easy_install` to extract the third-party dependencies here and install them upfront with `pip`.
|
||||
python setup.py egg_info
|
||||
# The requires.txt cannot be used with `pip install -r` directly. The requirements are listed at the top and the
|
||||
# optional dependencies come in non-standard syntax after a blank line. Thus, we just extract the header.
|
||||
sed -e '/^$/,$d' *.egg-info/requires.txt | tee requirements.txt
|
||||
pip install --progress-bar=off -r requirements.txt
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::Install TorchVision'
|
||||
python setup.py develop
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::Install torchvision-extra-decoders'
|
||||
# This can be done after torchvision was built
|
||||
if [[ "$(uname)" == "Linux" && "$(uname -m)" != "aarch64" ]]; then
|
||||
extra_decoders_channel="--pre --index-url https://download.pytorch.org/whl/nightly/cpu"
|
||||
else
|
||||
extra_decoders_channel=""
|
||||
fi
|
||||
|
||||
pip install torchvision-extra-decoders $extra_decoders_channel
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::Collect environment information'
|
||||
conda list
|
||||
python -m torch.utils.collect_env
|
||||
echo '::endgroup::'
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
./.github/scripts/setup-env.sh
|
||||
|
||||
# Activate conda environment
|
||||
eval "$($(which conda) shell.bash hook)" && conda deactivate && conda activate ci
|
||||
|
||||
echo '::group::Install testing utilities'
|
||||
# TODO: remove the <8 constraint on pytest when https://github.com/pytorch/vision/issues/8238 is closed
|
||||
pip install --progress-bar=off "pytest<8" pytest-mock pytest-cov expecttest!=0.2.0 requests
|
||||
echo '::endgroup::'
|
||||
|
||||
python test/smoke_test.py
|
||||
|
||||
# We explicitly ignore the video tests until we resolve https://github.com/pytorch/vision/issues/8162
|
||||
pytest --ignore-glob="*test_video*" --ignore-glob="*test_onnx*" --junit-xml="${RUNNER_TEST_RESULTS_DIR}/test-results.xml" -v --durations=25 -k "not TestFxFeatureExtraction"
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
name: CMake
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- nightly
|
||||
- main
|
||||
- release/*
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- runner: linux.12xlarge
|
||||
gpu-arch-type: cpu
|
||||
- runner: linux.g5.4xlarge.nvidia.gpu
|
||||
gpu-arch-type: cuda
|
||||
gpu-arch-version: "11.8"
|
||||
fail-fast: false
|
||||
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
runner: ${{ matrix.runner }}
|
||||
gpu-arch-type: ${{ matrix.gpu-arch-type }}
|
||||
gpu-arch-version: ${{ matrix.gpu-arch-version }}
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
export PYTHON_VERSION=3.9
|
||||
export GPU_ARCH_TYPE=${{ matrix.gpu-arch-type }}
|
||||
export GPU_ARCH_VERSION=${{ matrix.gpu-arch-version }}
|
||||
./.github/scripts/cmake.sh
|
||||
|
||||
macos:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- runner: macos-m1-stable
|
||||
fail-fast: false
|
||||
uses: pytorch/test-infra/.github/workflows/macos_job.yml@main
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
runner: ${{ matrix.runner }}
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
export PYTHON_VERSION=3.9
|
||||
export GPU_ARCH_TYPE=cpu
|
||||
export GPU_ARCH_VERSION=''
|
||||
|
||||
${CONDA_RUN} ./.github/scripts/cmake.sh
|
||||
|
||||
windows:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- runner: windows.4xlarge
|
||||
gpu-arch-type: cpu
|
||||
- runner: windows.g5.4xlarge.nvidia.gpu
|
||||
gpu-arch-type: cuda
|
||||
gpu-arch-version: "11.8"
|
||||
fail-fast: false
|
||||
uses: pytorch/test-infra/.github/workflows/windows_job.yml@main
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
runner: ${{ matrix.runner }}
|
||||
gpu-arch-type: ${{ matrix.gpu-arch-type }}
|
||||
gpu-arch-version: ${{ matrix.gpu-arch-version }}
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
export PYTHON_VERSION=3.9
|
||||
export VC_YEAR=2022
|
||||
export VSDEVCMD_ARGS=""
|
||||
export GPU_ARCH_TYPE=${{ matrix.gpu-arch-type }}
|
||||
export GPU_ARCH_VERSION=${{ matrix.gpu-arch-version }}
|
||||
|
||||
./.github/scripts/cmake.sh
|
||||
54
cache/torch/hub/pytorch_vision_main/.github/workflows/build-wheels-aarch64-linux.yml
vendored
Normal file
54
cache/torch/hub/pytorch_vision_main/.github/workflows/build-wheels-aarch64-linux.yml
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
name: Build Aarch64 Linux Wheels
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- nightly
|
||||
- main
|
||||
- release/*
|
||||
tags:
|
||||
# NOTE: Binary build pipelines should only get triggered on release candidate builds
|
||||
# Release candidate tags look like: v1.11.0-rc1
|
||||
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
generate-matrix:
|
||||
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
|
||||
with:
|
||||
package-type: wheel
|
||||
os: linux-aarch64
|
||||
test-infra-repository: pytorch/test-infra
|
||||
test-infra-ref: main
|
||||
with-cuda: disable
|
||||
build:
|
||||
needs: generate-matrix
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- repository: pytorch/vision
|
||||
pre-script: packaging/pre_build_script.sh
|
||||
post-script: packaging/post_build_script.sh
|
||||
smoke-test-script: test/smoke_test.py
|
||||
package-name: torchvision
|
||||
name: ${{ matrix.repository }}
|
||||
uses: pytorch/test-infra/.github/workflows/build_wheels_linux.yml@main
|
||||
with:
|
||||
repository: ${{ matrix.repository }}
|
||||
ref: ""
|
||||
test-infra-repository: pytorch/test-infra
|
||||
test-infra-ref: main
|
||||
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
|
||||
pre-script: ${{ matrix.pre-script }}
|
||||
post-script: ${{ matrix.post-script }}
|
||||
package-name: ${{ matrix.package-name }}
|
||||
smoke-test-script: ${{ matrix.smoke-test-script }}
|
||||
trigger-event: ${{ github.event_name }}
|
||||
architecture: aarch64
|
||||
setup-miniconda: false
|
||||
52
cache/torch/hub/pytorch_vision_main/.github/workflows/build-wheels-linux.yml
vendored
Normal file
52
cache/torch/hub/pytorch_vision_main/.github/workflows/build-wheels-linux.yml
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
name: Build Linux Wheels
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- nightly
|
||||
- main
|
||||
- release/*
|
||||
tags:
|
||||
# NOTE: Binary build pipelines should only get triggered on release candidate builds
|
||||
# Release candidate tags look like: v1.11.0-rc1
|
||||
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
generate-matrix:
|
||||
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
|
||||
with:
|
||||
package-type: wheel
|
||||
os: linux
|
||||
test-infra-repository: pytorch/test-infra
|
||||
test-infra-ref: main
|
||||
with-xpu: enable
|
||||
build:
|
||||
needs: generate-matrix
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- repository: pytorch/vision
|
||||
pre-script: packaging/pre_build_script.sh
|
||||
post-script: packaging/post_build_script.sh
|
||||
smoke-test-script: test/smoke_test.py
|
||||
package-name: torchvision
|
||||
name: ${{ matrix.repository }}
|
||||
uses: pytorch/test-infra/.github/workflows/build_wheels_linux.yml@main
|
||||
with:
|
||||
repository: ${{ matrix.repository }}
|
||||
ref: ""
|
||||
test-infra-repository: pytorch/test-infra
|
||||
test-infra-ref: main
|
||||
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
|
||||
pre-script: ${{ matrix.pre-script }}
|
||||
post-script: ${{ matrix.post-script }}
|
||||
package-name: ${{ matrix.package-name }}
|
||||
smoke-test-script: ${{ matrix.smoke-test-script }}
|
||||
trigger-event: ${{ github.event_name }}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
name: Build M1 Wheels
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- nightly
|
||||
- main
|
||||
- release/*
|
||||
tags:
|
||||
# NOTE: Binary build pipelines should only get triggered on release candidate builds
|
||||
# Release candidate tags look like: v1.11.0-rc1
|
||||
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
generate-matrix:
|
||||
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
|
||||
with:
|
||||
package-type: wheel
|
||||
os: macos-arm64
|
||||
test-infra-repository: pytorch/test-infra
|
||||
test-infra-ref: main
|
||||
build:
|
||||
needs: generate-matrix
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- repository: pytorch/vision
|
||||
pre-script: packaging/pre_build_script.sh
|
||||
post-script: packaging/post_build_script.sh
|
||||
smoke-test-script: test/smoke_test.py
|
||||
package-name: torchvision
|
||||
name: ${{ matrix.repository }}
|
||||
uses: pytorch/test-infra/.github/workflows/build_wheels_macos.yml@main
|
||||
with:
|
||||
repository: ${{ matrix.repository }}
|
||||
ref: ""
|
||||
test-infra-repository: pytorch/test-infra
|
||||
test-infra-ref: main
|
||||
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
|
||||
pre-script: ${{ matrix.pre-script }}
|
||||
post-script: ${{ matrix.post-script }}
|
||||
package-name: ${{ matrix.package-name }}
|
||||
runner-type: macos-m1-stable
|
||||
smoke-test-script: ${{ matrix.smoke-test-script }}
|
||||
trigger-event: ${{ github.event_name }}
|
||||
54
cache/torch/hub/pytorch_vision_main/.github/workflows/build-wheels-windows.yml
vendored
Normal file
54
cache/torch/hub/pytorch_vision_main/.github/workflows/build-wheels-windows.yml
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
name: Build Windows Wheels
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- nightly
|
||||
- main
|
||||
- release/*
|
||||
tags:
|
||||
# NOTE: Binary build pipelines should only get triggered on release candidate builds
|
||||
# Release candidate tags look like: v1.11.0-rc1
|
||||
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
generate-matrix:
|
||||
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
|
||||
with:
|
||||
package-type: wheel
|
||||
os: windows
|
||||
test-infra-repository: pytorch/test-infra
|
||||
test-infra-ref: main
|
||||
with-xpu: enable
|
||||
build:
|
||||
needs: generate-matrix
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- repository: pytorch/vision
|
||||
pre-script: packaging/pre_build_script.sh
|
||||
env-script: packaging/windows/internal/vc_env_helper.bat
|
||||
post-script: "python packaging/wheel/relocate.py"
|
||||
smoke-test-script: test/smoke_test.py
|
||||
package-name: torchvision
|
||||
name: ${{ matrix.repository }}
|
||||
uses: pytorch/test-infra/.github/workflows/build_wheels_windows.yml@main
|
||||
with:
|
||||
repository: ${{ matrix.repository }}
|
||||
ref: ""
|
||||
test-infra-repository: pytorch/test-infra
|
||||
test-infra-ref: main
|
||||
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
|
||||
pre-script: ${{ matrix.pre-script }}
|
||||
env-script: ${{ matrix.env-script }}
|
||||
post-script: ${{ matrix.post-script }}
|
||||
package-name: ${{ matrix.package-name }}
|
||||
smoke-test-script: ${{ matrix.smoke-test-script }}
|
||||
trigger-event: ${{ github.event_name }}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
name: Docs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- nightly
|
||||
- main
|
||||
- release/*
|
||||
tags:
|
||||
- v[0-9]+.[0-9]+.[0-9]
|
||||
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
upload-artifact: docs
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
export PYTHON_VERSION=3.10
|
||||
export GPU_ARCH_TYPE=cpu
|
||||
export GPU_ARCH_VERSION=''
|
||||
./.github/scripts/setup-env.sh
|
||||
|
||||
# Prepare conda
|
||||
CONDA_PATH=$(which conda)
|
||||
eval "$(${CONDA_PATH} shell.bash hook)"
|
||||
conda activate ci
|
||||
# FIXME: not sure why we need this. `ldd torchvision/video_reader.so` shows that it
|
||||
# already links against the one pulled from conda. However, at runtime it pulls from
|
||||
# /lib64
|
||||
# Should we maybe always do this in `./.github/scripts/setup-env.sh` so that we don't
|
||||
# have to pay attention in all other workflows?
|
||||
export LD_LIBRARY_PATH="${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH}"
|
||||
|
||||
cd docs
|
||||
|
||||
echo '::group::Install doc requirements'
|
||||
pip install --progress-bar=off -r requirements.txt
|
||||
echo '::endgroup::'
|
||||
|
||||
if [[ ${{ github.event_name }} == push && (${{ github.ref_type }} == tag || (${{ github.ref_type }} == branch && ${{ github.ref_name }} == release/*)) ]]; then
|
||||
echo '::group::Enable version string sanitization'
|
||||
# This environment variable just has to exist and must not be empty. The actual value is arbitrary.
|
||||
# See docs/source/conf.py for details
|
||||
export TORCHVISION_SANITIZE_VERSION_STR_IN_DOCS=1
|
||||
echo '::endgroup::'
|
||||
fi
|
||||
|
||||
# The runner does not have sufficient memory to run with as many processes as there are
|
||||
# cores (`-j auto`). Thus, we limit to a single process (`-j 1`) here.
|
||||
sed -i -e 's/-j auto/-j 1/' Makefile
|
||||
make html
|
||||
|
||||
# Below is an imperfect way for us to add "try on Colab" links to all of our gallery examples.
|
||||
# sphinx-gallery will convert all gallery examples to .ipynb notebooks and stores them in
|
||||
# build/html/_downloads/<some_hash>/<example_name>.ipynb
|
||||
# We copy all those ipynb files in a more convenient folder so that we can more easily link to them.
|
||||
mkdir build/html/_generated_ipynb_notebooks
|
||||
for file in `find build/html/_downloads`; do
|
||||
if [[ $file == *.ipynb ]]; then
|
||||
cp $file build/html/_generated_ipynb_notebooks/
|
||||
fi
|
||||
done
|
||||
|
||||
cp -r build/html "${RUNNER_ARTIFACT_DIR}"
|
||||
|
||||
# On PRs we also want to upload the docs into our S3 bucket for preview.
|
||||
if [[ ${{ github.event_name == 'pull_request' }} ]]; then
|
||||
cp -r build/html/* "${RUNNER_DOCS_DIR}"
|
||||
fi
|
||||
|
||||
upload:
|
||||
needs: build
|
||||
if: github.repository == 'pytorch/vision' && github.event_name == 'push' &&
|
||||
((github.ref_type == 'branch' && github.ref_name == 'main') || github.ref_type == 'tag')
|
||||
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
download-artifact: docs
|
||||
ref: gh-pages
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
REF_TYPE=${{ github.ref_type }}
|
||||
REF_NAME=${{ github.ref_name }}
|
||||
|
||||
if [[ "${REF_TYPE}" == branch ]]; then
|
||||
TARGET_FOLDER="${REF_NAME}"
|
||||
elif [[ "${REF_TYPE}" == tag ]]; then
|
||||
case "${REF_NAME}" in
|
||||
*-rc*)
|
||||
echo "Aborting upload since this is an RC tag: ${REF_NAME}"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
# Strip the leading "v" as well as the trailing patch version. For example:
|
||||
# 'v0.15.2' -> '0.15'
|
||||
TARGET_FOLDER=$(echo "${REF_NAME}" | sed 's/v\([0-9]\+\)\.\([0-9]\+\)\.[0-9]\+/\1.\2/')
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
echo "Target Folder: ${TARGET_FOLDER}"
|
||||
|
||||
mkdir -p "${TARGET_FOLDER}"
|
||||
rm -rf "${TARGET_FOLDER}"/*
|
||||
mv "${RUNNER_ARTIFACT_DIR}"/html/* "${TARGET_FOLDER}"
|
||||
git add "${TARGET_FOLDER}" || true
|
||||
|
||||
if [[ "${TARGET_FOLDER}" == main ]]; then
|
||||
mkdir -p _static
|
||||
rm -rf _static/*
|
||||
cp -r "${TARGET_FOLDER}"/_static/* _static
|
||||
git add _static || true
|
||||
fi
|
||||
|
||||
git config user.name 'pytorchbot'
|
||||
git config user.email 'soumith+bot@pytorch.org'
|
||||
git config http.postBuffer 524288000
|
||||
git commit -m "auto-generating sphinx docs" || true
|
||||
git push
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- nightly
|
||||
- main
|
||||
- release/*
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
python-source-and-configs:
|
||||
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
echo '::group::Setup environment'
|
||||
CONDA_PATH=$(which conda)
|
||||
eval "$(${CONDA_PATH} shell.bash hook)"
|
||||
conda create --name ci --quiet --yes python=3.9 pip
|
||||
conda activate ci
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::Install lint tools'
|
||||
pip install --progress-bar=off pre-commit
|
||||
echo '::endgroup::'
|
||||
|
||||
set +e
|
||||
pre-commit run --all-files
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
git --no-pager diff
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# c-source:
|
||||
# uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
|
||||
# permissions:
|
||||
# id-token: write
|
||||
# contents: read
|
||||
# with:
|
||||
# repository: pytorch/vision
|
||||
# test-infra-ref: main
|
||||
# script: |
|
||||
# set -euo pipefail
|
||||
|
||||
# echo '::group::Setup environment'
|
||||
# CONDA_PATH=$(which conda)
|
||||
# eval "$(${CONDA_PATH} shell.bash hook)"
|
||||
# conda create --name ci --quiet --yes -c conda-forge python=3.9 clang-format
|
||||
# conda activate ci
|
||||
# echo '::endgroup::'
|
||||
|
||||
|
||||
# echo '::group::Lint C source'
|
||||
# set +e
|
||||
# ./.github/scripts/run-clang-format.py -r torchvision/csrc --exclude "torchvision/csrc/io/image/cpu/giflib/*"
|
||||
|
||||
# if [ $? -ne 0 ]; then
|
||||
# git --no-pager diff
|
||||
# exit 1
|
||||
# fi
|
||||
# echo '::endgroup::'
|
||||
|
||||
|
||||
python-types:
|
||||
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
export PYTHON_VERSION=3.11
|
||||
export GPU_ARCH_TYPE=cpu
|
||||
export GPU_ARCH_VERSION=''
|
||||
|
||||
./.github/scripts/setup-env.sh
|
||||
|
||||
CONDA_PATH=$(which conda)
|
||||
eval "$(${CONDA_PATH} shell.bash hook)"
|
||||
conda activate ci
|
||||
|
||||
echo '::group::Install lint tools'
|
||||
pip install --progress-bar=off "mypy==1.13.0"
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::Lint Python types'
|
||||
mypy --install-types --non-interactive --config-file mypy.ini
|
||||
echo '::endgroup::'
|
||||
|
||||
# bc:
|
||||
# if: github.event.pull_request
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Run BC Lint Action
|
||||
# uses: pytorch/test-infra/.github/actions/bc-lint@main
|
||||
# with:
|
||||
# repo: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
# base_sha: ${{ github.event.pull_request.base.sha }}
|
||||
# head_sha: ${{ github.event.pull_request.head.sha }}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
name: pr-labels
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
is-properly-labeled:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
- name: Install requests
|
||||
run: pip install requests
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Process commit and find merger responsible for labeling
|
||||
id: commit
|
||||
run: |
|
||||
MERGER=$(python .github/process_commit.py ${{ github.sha }})
|
||||
echo "merger=${MERGER}" | tee --append $GITHUB_OUTPUT
|
||||
|
||||
- name: Ping merger responsible for labeling if necessary
|
||||
if: ${{ steps.commit.outputs.merger != '' }}
|
||||
uses: mshick/add-pr-comment@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
message: |
|
||||
Hey ${{ steps.commit.outputs.merger }}!
|
||||
|
||||
You merged this PR, but no labels were added.
|
||||
The list of valid labels is available at https://github.com/pytorch/vision/blob/main/.github/process_commit.py
|
||||
60
cache/torch/hub/pytorch_vision_main/.github/workflows/prototype-tests-linux-gpu.yml
vendored
Normal file
60
cache/torch/hub/pytorch_vision_main/.github/workflows/prototype-tests-linux-gpu.yml
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
name: Prototype tests on Linux
|
||||
|
||||
# IMPORTANT: This workflow has been manually disabled from the GitHub interface
|
||||
# in June 2024. The file is kept for reference in case we ever put this back.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
unittests-prototype:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
runner: ["linux.12xlarge"]
|
||||
gpu-arch-type: ["cpu"]
|
||||
include:
|
||||
- python-version: "3.9"
|
||||
runner: linux.g5.4xlarge.nvidia.gpu
|
||||
gpu-arch-type: cuda
|
||||
gpu-arch-version: "11.8"
|
||||
fail-fast: false
|
||||
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
runner: ${{ matrix.runner }}
|
||||
gpu-arch-type: ${{ matrix.gpu-arch-type }}
|
||||
gpu-arch-version: ${{ matrix.gpu-arch-version }}
|
||||
timeout: 120
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
export PYTHON_VERSION=${{ matrix.python-version }}
|
||||
export GPU_ARCH_TYPE=${{ matrix.gpu-arch-type }}
|
||||
export GPU_ARCH_VERSION=${{ matrix.gpu-arch-version }}
|
||||
./.github/scripts/setup-env.sh
|
||||
|
||||
# Prepare conda
|
||||
CONDA_PATH=$(which conda)
|
||||
eval "$(${CONDA_PATH} shell.bash hook)"
|
||||
conda activate ci
|
||||
|
||||
echo '::group::Install testing utilities'
|
||||
pip install --progress-bar=off pytest pytest-mock pytest-cov
|
||||
echo '::endgroup::'
|
||||
|
||||
# We don't want to run the prototype datasets tests. Since the positional glob into `pytest`, i.e.
|
||||
# `test/test_prototype*.py` takes the highest priority, neither `--ignore` nor `--ignore-glob` can help us here.
|
||||
rm test/test_prototype_datasets*.py
|
||||
pytest \
|
||||
-v --durations=25 \
|
||||
--cov=torchvision/prototype --cov-report=term-missing \
|
||||
--junit-xml="${RUNNER_TEST_RESULTS_DIR}/test-results.xml" \
|
||||
test/test_prototype_*.py
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
name: tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "test/test_datasets_download.py"
|
||||
- ".github/failed_schedule_issue_template.md"
|
||||
- ".github/workflows/tests-schedule.yml"
|
||||
|
||||
schedule:
|
||||
- cron: "0 9 * * *"
|
||||
|
||||
jobs:
|
||||
download:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.9
|
||||
|
||||
- name: Upgrade system packages
|
||||
run: python -m pip install --upgrade pip setuptools wheel
|
||||
|
||||
- name: SSL
|
||||
run: python -c 'import ssl; print(ssl.OPENSSL_VERSION)'
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: TODO REMOVE THIS! Install non pre-release version of mpmath.
|
||||
run: pip install "mpmath<1.4"
|
||||
|
||||
- name: Install torch nightly build
|
||||
run: pip install --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html
|
||||
|
||||
- name: Install torchvision
|
||||
run: pip install --no-build-isolation --editable .
|
||||
|
||||
- name: Install all optional dataset requirements
|
||||
run: pip install scipy pycocotools lmdb gdown
|
||||
|
||||
- name: Install tests requirements
|
||||
run: pip install pytest
|
||||
|
||||
- name: Run tests
|
||||
run: pytest -ra -v test/test_datasets_download.py
|
||||
|
||||
- uses: JasonEtco/create-an-issue@v2.4.0
|
||||
name: Create issue if download tests failed
|
||||
if: failure() && github.event_name == 'schedule'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
WORKFLOW: ${{ github.workflow }}
|
||||
JOB: ${{ github.job }}
|
||||
ID: ${{ github.run_id }}
|
||||
with:
|
||||
filename: .github/failed_schedule_issue_template.md
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
name: Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- nightly
|
||||
- main
|
||||
- release/*
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
unittests-linux:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
runner: ["linux.12xlarge"]
|
||||
gpu-arch-type: ["cpu"]
|
||||
include:
|
||||
- python-version: 3.9
|
||||
runner: linux.g5.4xlarge.nvidia.gpu
|
||||
gpu-arch-type: cuda
|
||||
gpu-arch-version: "11.8"
|
||||
fail-fast: false
|
||||
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
runner: ${{ matrix.runner }}
|
||||
gpu-arch-type: ${{ matrix.gpu-arch-type }}
|
||||
gpu-arch-version: ${{ matrix.gpu-arch-version }}
|
||||
timeout: 120
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
export PYTHON_VERSION=${{ matrix.python-version }}
|
||||
export GPU_ARCH_TYPE=${{ matrix.gpu-arch-type }}
|
||||
export GPU_ARCH_VERSION=${{ matrix.gpu-arch-version }}
|
||||
|
||||
./.github/scripts/unittest.sh
|
||||
|
||||
unittests-macos:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
# TODO put back 3.11 (See blame)
|
||||
# - "3.11"
|
||||
- "3.12"
|
||||
runner: ["macos-m1-stable"]
|
||||
fail-fast: false
|
||||
uses: pytorch/test-infra/.github/workflows/macos_job.yml@main
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
timeout: 240
|
||||
runner: ${{ matrix.runner }}
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
export PYTHON_VERSION=${{ matrix.python-version }}
|
||||
export GPU_ARCH_TYPE=cpu
|
||||
export GPU_ARCH_VERSION=''
|
||||
|
||||
${CONDA_RUN} ./.github/scripts/unittest.sh
|
||||
|
||||
unittests-windows:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
runner: ["windows.4xlarge"]
|
||||
gpu-arch-type: ["cpu"]
|
||||
# TODO: put GPU testing back
|
||||
# include:
|
||||
# - python-version: "3.9"
|
||||
# runner: windows.g5.4xlarge.nvidia.gpu
|
||||
# gpu-arch-type: cuda
|
||||
# gpu-arch-version: "11.8"
|
||||
fail-fast: false
|
||||
uses: pytorch/test-infra/.github/workflows/windows_job.yml@main
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
runner: ${{ matrix.runner }}
|
||||
gpu-arch-type: ${{ matrix.gpu-arch-type }}
|
||||
gpu-arch-version: ${{ matrix.gpu-arch-version }}
|
||||
timeout: 120
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euxo pipefail
|
||||
|
||||
export PYTHON_VERSION=${{ matrix.python-version }}
|
||||
export VC_YEAR=2022
|
||||
export VSDEVCMD_ARGS=""
|
||||
export GPU_ARCH_TYPE=${{ matrix.gpu-arch-type }}
|
||||
export GPU_ARCH_VERSION=${{ matrix.gpu-arch-version }}
|
||||
|
||||
./.github/scripts/unittest.sh
|
||||
|
||||
# onnx:
|
||||
# uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
|
||||
# permissions:
|
||||
# id-token: write
|
||||
# contents: read
|
||||
# with:
|
||||
# repository: pytorch/vision
|
||||
# test-infra-ref: main
|
||||
# script: |
|
||||
# set -euo pipefail
|
||||
|
||||
# export PYTHON_VERSION=3.10
|
||||
# export GPU_ARCH_TYPE=cpu
|
||||
# export GPU_ARCH_VERSION=''
|
||||
|
||||
# ./.github/scripts/setup-env.sh
|
||||
|
||||
# # Prepare conda
|
||||
# CONDA_PATH=$(which conda)
|
||||
# eval "$(${CONDA_PATH} shell.bash hook)"
|
||||
# conda activate ci
|
||||
|
||||
# echo '::group::Install ONNX'
|
||||
# pip install --progress-bar=off onnx onnxruntime
|
||||
# echo '::endgroup::'
|
||||
|
||||
# echo '::group::Install testing utilities'
|
||||
# pip install --progress-bar=off pytest "numpy<2"
|
||||
# echo '::endgroup::'
|
||||
|
||||
# echo '::group::Run ONNX tests'
|
||||
# pytest --junit-xml="${RUNNER_TEST_RESULTS_DIR}/test-results.xml" -v --durations=25 test/test_onnx.py
|
||||
# echo '::endgroup::'
|
||||
|
||||
unittests-extended:
|
||||
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
if: contains(github.event.pull_request.labels.*.name, 'run-extended')
|
||||
with:
|
||||
repository: pytorch/vision
|
||||
test-infra-ref: main
|
||||
script: |
|
||||
set -euo pipefail
|
||||
|
||||
export PYTHON_VERSION=3.9
|
||||
export GPU_ARCH_TYPE=cpu
|
||||
export GPU_ARCH_VERSION=''
|
||||
|
||||
./.github/scripts/setup-env.sh
|
||||
|
||||
# Prepare conda
|
||||
CONDA_PATH=$(which conda)
|
||||
eval "$(${CONDA_PATH} shell.bash hook)"
|
||||
conda activate ci
|
||||
|
||||
echo '::group::Pre-download model weights'
|
||||
pip install --progress-bar=off aiohttp aiofiles tqdm
|
||||
python scripts/download_model_urls.py
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::Install testing utilities'
|
||||
# TODO: remove the <8 constraint on pytest when https://github.com/pytorch/vision/issues/8238 is closed
|
||||
pip install --progress-bar=off "pytest<8"
|
||||
echo '::endgroup::'
|
||||
|
||||
echo '::group::Run extended unittests'
|
||||
export PYTORCH_TEST_WITH_EXTENDED=1
|
||||
pytest --junit-xml="${RUNNER_TEST_RESULTS_DIR}/test-results.xml" -v --durations=25 test/test_extended_*.py
|
||||
echo '::endgroup::'
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
build/
|
||||
dist/
|
||||
torchvision.egg-info/
|
||||
torchvision/version.py
|
||||
*/**/__pycache__
|
||||
*/__pycache__
|
||||
*/*.pyc
|
||||
*/**/*.pyc
|
||||
*/**/**/*.pyc
|
||||
*/**/*~
|
||||
*~
|
||||
|
||||
docs/build
|
||||
# sphinx-gallery
|
||||
docs/source/auto_examples/
|
||||
docs/source/gen_modules/
|
||||
docs/source/generated/
|
||||
docs/source/models/generated/
|
||||
docs/source/sg_execution_times.rst
|
||||
# pytorch-sphinx-theme gets installed here
|
||||
docs/src
|
||||
|
||||
.coverage
|
||||
htmlcov
|
||||
.*.swp
|
||||
*.so*
|
||||
*.dylib*
|
||||
*/*.so*
|
||||
*/*.dylib*
|
||||
*.swp
|
||||
*.swo
|
||||
gen.yml
|
||||
.mypy_cache
|
||||
.vscode/
|
||||
.idea/
|
||||
*.orig
|
||||
*-checkpoint.ipynb
|
||||
*.venv
|
||||
|
||||
## Xcode User settings
|
||||
xcuserdata/
|
||||
|
||||
# direnv
|
||||
.direnv
|
||||
.envrc
|
||||
|
||||
scripts/release_notes/data.json
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.0.1
|
||||
hooks:
|
||||
- id: check-docstring-first
|
||||
- id: check-toml
|
||||
- id: check-yaml
|
||||
exclude: packaging/.*
|
||||
args:
|
||||
- --allow-multiple-documents
|
||||
- id: mixed-line-ending
|
||||
args: [--fix=lf]
|
||||
- id: end-of-file-fixer
|
||||
|
||||
- repo: https://github.com/omnilib/ufmt
|
||||
rev: v1.3.3
|
||||
hooks:
|
||||
- id: ufmt
|
||||
additional_dependencies:
|
||||
- black == 22.3.0
|
||||
- usort == 1.0.2
|
||||
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 5.0.4
|
||||
hooks:
|
||||
- id: flake8
|
||||
args: [--config=setup.cfg]
|
||||
|
||||
- repo: https://github.com/PyCQA/pydocstyle
|
||||
rev: 6.1.1
|
||||
hooks:
|
||||
- id: pydocstyle
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
cff-version: 1.2.0
|
||||
title: "TorchVision: PyTorch's Computer Vision library"
|
||||
message: >-
|
||||
If you find TorchVision useful in your work, please
|
||||
consider citing the following BibTeX entry.
|
||||
type: software
|
||||
authors:
|
||||
- given-names: TorchVision maintainers and contributors
|
||||
url: "https://github.com/pytorch/vision"
|
||||
license: "BSD-3-Clause"
|
||||
date-released: "2016-11-06"
|
||||
journal: "GitHub repository"
|
||||
publisher: "GitHub"
|
||||
key: "torchvision2016"
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
cmake_minimum_required(VERSION 3.18)
|
||||
project(torchvision)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
file(STRINGS version.txt TORCHVISION_VERSION)
|
||||
|
||||
option(WITH_CUDA "Enable CUDA support" OFF)
|
||||
option(WITH_MPS "Enable MPS support" OFF)
|
||||
option(WITH_PNG "Enable features requiring LibPNG." ON)
|
||||
option(WITH_JPEG "Enable features requiring LibJPEG." ON)
|
||||
# Libwebp is disabled by default, which means enabling it from cmake is largely
|
||||
# untested. Since building from cmake is very low pri anyway, this is OK. If
|
||||
# you're a user and you need this, please open an issue (and a PR!).
|
||||
option(WITH_WEBP "Enable features requiring LibWEBP." OFF)
|
||||
# Same here
|
||||
option(WITH_AVIF "Enable features requiring LibAVIF." OFF)
|
||||
|
||||
if(WITH_CUDA)
|
||||
enable_language(CUDA)
|
||||
add_definitions(-D__CUDA_NO_HALF_OPERATORS__)
|
||||
add_definitions(-DWITH_CUDA)
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr")
|
||||
endif()
|
||||
|
||||
if(WITH_MPS)
|
||||
enable_language(OBJC OBJCXX)
|
||||
add_definitions(-DWITH_MPS)
|
||||
endif()
|
||||
|
||||
find_package(Torch REQUIRED)
|
||||
|
||||
if (WITH_PNG)
|
||||
add_definitions(-DPNG_FOUND)
|
||||
find_package(PNG REQUIRED)
|
||||
endif()
|
||||
|
||||
if (WITH_JPEG)
|
||||
add_definitions(-DJPEG_FOUND)
|
||||
find_package(JPEG REQUIRED)
|
||||
endif()
|
||||
|
||||
if (WITH_WEBP)
|
||||
add_definitions(-DWEBP_FOUND)
|
||||
find_package(WEBP REQUIRED)
|
||||
endif()
|
||||
|
||||
if (WITH_AVIF)
|
||||
add_definitions(-DAVIF_FOUND)
|
||||
find_package(AVIF REQUIRED)
|
||||
endif()
|
||||
|
||||
function(CUDA_CONVERT_FLAGS EXISTING_TARGET)
|
||||
get_property(old_flags TARGET ${EXISTING_TARGET} PROPERTY INTERFACE_COMPILE_OPTIONS)
|
||||
if(NOT "${old_flags}" STREQUAL "")
|
||||
string(REPLACE ";" "," CUDA_flags "${old_flags}")
|
||||
set_property(TARGET ${EXISTING_TARGET} PROPERTY INTERFACE_COMPILE_OPTIONS
|
||||
"$<$<BUILD_INTERFACE:$<COMPILE_LANGUAGE:CXX>>:${old_flags}>$<$<BUILD_INTERFACE:$<COMPILE_LANGUAGE:CUDA>>:-Xcompiler=${CUDA_flags}>"
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4819")
|
||||
if(WITH_CUDA)
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=/wd4819")
|
||||
foreach(diag cc_clobber_ignored integer_sign_change useless_using_declaration
|
||||
set_but_not_used field_without_dll_interface
|
||||
base_class_has_different_dll_interface
|
||||
dll_interface_conflict_none_assumed
|
||||
dll_interface_conflict_dllexport_assumed
|
||||
implicit_return_from_non_void_function
|
||||
unsigned_compare_with_zero
|
||||
declared_but_not_referenced
|
||||
bad_friend_decl)
|
||||
string(APPEND CMAKE_CUDA_FLAGS " -Xcudafe --diag_suppress=${diag}")
|
||||
endforeach()
|
||||
CUDA_CONVERT_FLAGS(torch_cpu)
|
||||
if(TARGET torch_cuda)
|
||||
CUDA_CONVERT_FLAGS(torch_cuda)
|
||||
endif()
|
||||
if(TARGET torch_cuda_cu)
|
||||
CUDA_CONVERT_FLAGS(torch_cuda_cu)
|
||||
endif()
|
||||
if(TARGET torch_cuda_cpp)
|
||||
CUDA_CONVERT_FLAGS(torch_cuda_cpp)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
set(TVCPP torchvision/csrc)
|
||||
list(APPEND ALLOW_LISTED ${TVCPP} ${TVCPP}/io/image ${TVCPP}/io/image/cpu ${TVCPP}/io/image/cpu/giflib ${TVCPP}/models ${TVCPP}/ops
|
||||
${TVCPP}/ops/autograd ${TVCPP}/ops/cpu ${TVCPP}/io/image/cuda)
|
||||
if(WITH_CUDA)
|
||||
list(APPEND ALLOW_LISTED ${TVCPP}/ops/cuda ${TVCPP}/ops/autocast)
|
||||
endif()
|
||||
if(WITH_MPS)
|
||||
list(APPEND ALLOW_LISTED ${TVCPP}/ops/mps)
|
||||
endif()
|
||||
|
||||
FOREACH(DIR ${ALLOW_LISTED})
|
||||
file(GLOB ALL_SOURCES ${ALL_SOURCES} ${DIR}/*.*)
|
||||
ENDFOREACH()
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED ${ALL_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${TORCH_LIBRARIES})
|
||||
|
||||
if(WITH_MPS)
|
||||
find_library(metal NAMES Metal)
|
||||
find_library(foundation NAMES Foundation)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${metal} ${foundation})
|
||||
endif()
|
||||
|
||||
if (WITH_PNG)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${PNG_LIBRARY})
|
||||
endif()
|
||||
|
||||
if (WITH_JPEG)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${JPEG_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (WITH_WEBP)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${WEBP_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (WITH_AVIF)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${AVIF_LIBRARIES})
|
||||
endif()
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
EXPORT_NAME TorchVision
|
||||
INSTALL_RPATH ${TORCH_INSTALL_PREFIX}/lib)
|
||||
|
||||
include_directories(torchvision/csrc)
|
||||
|
||||
if (WITH_PNG)
|
||||
include_directories(${PNG_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if (WITH_JPEG)
|
||||
include_directories(${JPEG_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if (WITH_WEBP)
|
||||
include_directories(${WEBP_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if (WITH_AVIF)
|
||||
include_directories(${AVIF_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
set(TORCHVISION_CMAKECONFIG_INSTALL_DIR "share/cmake/TorchVision" CACHE STRING "install path for TorchVisionConfig.cmake")
|
||||
|
||||
configure_package_config_file(cmake/TorchVisionConfig.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/TorchVisionConfig.cmake"
|
||||
INSTALL_DESTINATION ${TORCHVISION_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/TorchVisionConfigVersion.cmake
|
||||
VERSION ${TORCHVISION_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/TorchVisionConfig.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/TorchVisionConfigVersion.cmake
|
||||
DESTINATION ${TORCHVISION_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
EXPORT TorchVisionTargets
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
install(EXPORT TorchVisionTargets
|
||||
NAMESPACE TorchVision::
|
||||
DESTINATION ${TORCHVISION_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
FOREACH(INPUT_DIR ${ALLOW_LISTED})
|
||||
string(REPLACE "${TVCPP}" "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}" OUTPUT_DIR ${INPUT_DIR})
|
||||
file(GLOB INPUT_FILES ${INPUT_DIR}/*.*)
|
||||
install(FILES ${INPUT_FILES} DESTINATION ${OUTPUT_DIR})
|
||||
ENDFOREACH()
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
# Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to make participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all project spaces, and it also applies when
|
||||
an individual is representing the project or its community in public spaces.
|
||||
Examples of representing a project or community include using an official
|
||||
project e-mail address, posting via an official social media account, or acting
|
||||
as an appointed representative at an online or offline event. Representation of
|
||||
a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at <conduct@pytorch.org>. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
# Contributing to Torchvision
|
||||
|
||||
We want to make contributing to this project as easy and transparent as possible.
|
||||
|
||||
## TL;DR
|
||||
|
||||
We appreciate all contributions. If you are interested in contributing to Torchvision, there are many ways to help out.
|
||||
Your contributions may fall into the following categories:
|
||||
|
||||
- It helps the project if you could
|
||||
- Report issues you're facing
|
||||
- Give a :+1: on issues that others reported and that are relevant to you
|
||||
|
||||
- Answering queries on the issue tracker, investigating bugs are very valuable contributions to the project.
|
||||
|
||||
- You would like to improve the documentation. This is no less important than improving the library itself!
|
||||
If you find a typo in the documentation, do not hesitate to submit a GitHub pull request.
|
||||
|
||||
- If you would like to fix a bug
|
||||
- please pick one from the [list of open issues labelled as "help wanted"](https://github.com/pytorch/vision/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
- comment on the issue that you want to work on this issue
|
||||
- send a PR with your fix, see below.
|
||||
|
||||
- If you plan to contribute new features, utility functions or extensions, please first open an issue and discuss the feature with us.
|
||||
|
||||
## Issues
|
||||
|
||||
We use GitHub issues to track public bugs. Please ensure your description is
|
||||
clear and has sufficient instructions to be able to reproduce the issue.
|
||||
|
||||
## Development installation
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
Start by installing the **nightly** build of PyTorch following the [official
|
||||
instructions](https://pytorch.org/get-started/locally/). Note that the official
|
||||
instructions may ask you to install torchvision itself. If you are doing development
|
||||
on torchvision, you should not install prebuilt torchvision packages.
|
||||
|
||||
**Optionally**, install `libpng` and `libjpeg-turbo` if you want to enable
|
||||
support for
|
||||
native encoding / decoding of PNG and JPEG formats in
|
||||
[torchvision.io](https://pytorch.org/vision/stable/io.html#image):
|
||||
|
||||
```bash
|
||||
conda install libpng libjpeg-turbo -c pytorch
|
||||
```
|
||||
|
||||
Note: you can use the `TORCHVISION_INCLUDE` and `TORCHVISION_LIBRARY`
|
||||
environment variables to tell the build system where to find those libraries if
|
||||
they are in specific locations. Take a look at
|
||||
[setup.py](https://github.com/pytorch/vision/blob/main/setup.py) for more
|
||||
details.
|
||||
|
||||
### Clone and install torchvision
|
||||
|
||||
```bash
|
||||
git clone https://github.com/pytorch/vision.git
|
||||
cd vision
|
||||
python setup.py develop # use install instead of develop if you don't care about development.
|
||||
# or, for OSX
|
||||
# MACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py develop
|
||||
# for C++ debugging, use DEBUG=1
|
||||
# DEBUG=1 python setup.py develop
|
||||
```
|
||||
|
||||
By default, GPU support is built if CUDA is found and `torch.cuda.is_available()` is true. It's possible to force
|
||||
building GPU support by setting `FORCE_CUDA=1` environment variable, which is useful when building a docker image.
|
||||
|
||||
We don't officially support building from source using `pip`, but _if_ you do, you'll need to use the
|
||||
`--no-build-isolation` flag.
|
||||
|
||||
#### Other development dependencies (some of these are needed to run tests):
|
||||
|
||||
```
|
||||
pip install expecttest flake8 typing mypy pytest pytest-mock scipy requests
|
||||
```
|
||||
|
||||
## Development Process
|
||||
|
||||
If you plan to modify the code or documentation, please follow the steps below:
|
||||
|
||||
1. Fork the repository and create your branch from `main`.
|
||||
2. If you have modified the code (new feature or bug-fix), please add unit tests.
|
||||
3. If you have changed APIs, update the documentation. Make sure the documentation builds.
|
||||
4. Ensure the test suite passes.
|
||||
5. Make sure your code passes the formatting checks (see below).
|
||||
|
||||
For more details about pull requests,
|
||||
please read [GitHub's guides](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request).
|
||||
|
||||
If you would like to contribute a new model, please see [here](#New-architecture-or-improved-model-weights).
|
||||
|
||||
If you would like to contribute a new dataset, please see [here](#New-dataset).
|
||||
|
||||
### Code formatting and typing
|
||||
|
||||
#### Formatting
|
||||
|
||||
The torchvision code is formatted by [black](https://black.readthedocs.io/en/stable/),
|
||||
and checked against pep8 compliance with [flake8](https://flake8.pycqa.org/en/latest/).
|
||||
Instead of relying directly on `black` however, we rely on
|
||||
[ufmt](https://github.com/omnilib/ufmt), for compatibility reasons with Facebook
|
||||
internal infrastructure.
|
||||
|
||||
To format your code, install `ufmt` with `pip install ufmt==1.3.3 black==22.3.0 usort==1.0.2` and use e.g.:
|
||||
|
||||
```bash
|
||||
ufmt format torchvision
|
||||
```
|
||||
|
||||
For the vast majority of cases, this is all you should need to run. For the
|
||||
formatting to be a bit faster, you can also choose to only apply `ufmt` to the
|
||||
files that were edited in your PR with e.g.:
|
||||
|
||||
```bash
|
||||
ufmt format `git diff main --name-only`
|
||||
```
|
||||
|
||||
Similarly, you can check for `flake8` errors with `flake8 torchvision`, although
|
||||
they should be fairly rare considering that most of the errors are automatically
|
||||
taken care of by `ufmt` already.
|
||||
|
||||
##### Pre-commit hooks
|
||||
|
||||
For convenience and **purely optionally**, you can rely on [pre-commit
|
||||
hooks](https://pre-commit.com/) which will run both `ufmt` and `flake8` prior to
|
||||
every commit.
|
||||
|
||||
First install the `pre-commit` package with `pip install pre-commit`, and then
|
||||
run `pre-commit install` at the root of the repo for the hooks to be set up -
|
||||
that's it.
|
||||
|
||||
Feel free to read the [pre-commit docs](https://pre-commit.com/#usage) to learn
|
||||
more and improve your workflow. You'll see for example that `pre-commit run
|
||||
--all-files` will run both `ufmt` and `flake8` without the need for you to
|
||||
commit anything, and that the `--no-verify` flag can be added to `git commit` to
|
||||
temporarily deactivate the hooks.
|
||||
|
||||
#### Type annotations
|
||||
|
||||
The codebase has type annotations, please make sure to add type hints if required. We use `mypy` tool for type checking:
|
||||
```bash
|
||||
mypy --config-file mypy.ini
|
||||
```
|
||||
|
||||
### Unit tests
|
||||
|
||||
Before running tests make sure to install [test dependencies](#other-development-dependencies-some-of-these-are-needed-to-run-tests).
|
||||
|
||||
If you have modified the code by adding a new feature or a bug-fix, please add unit tests for that. To run a specific
|
||||
test:
|
||||
```bash
|
||||
pytest test/<test-module.py> -vvv -k <test_myfunc>
|
||||
# e.g. pytest test/test_transforms.py -vvv -k test_center_crop
|
||||
```
|
||||
|
||||
If you would like to run all tests:
|
||||
```bash
|
||||
pytest test -vvv
|
||||
```
|
||||
|
||||
Tests that require internet access should be in
|
||||
`test/test_internet.py`.
|
||||
|
||||
### Documentation
|
||||
|
||||
Torchvision uses [Google style](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html)
|
||||
for formatting docstrings. Length of line inside docstrings block must be limited to 120 characters.
|
||||
|
||||
Please, follow the instructions to build and deploy the documentation locally.
|
||||
|
||||
#### Install requirements
|
||||
|
||||
```bash
|
||||
cd docs
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### Build
|
||||
|
||||
```bash
|
||||
cd docs
|
||||
make html-noplot
|
||||
```
|
||||
|
||||
Then open `docs/build/html/index.html` in your favorite browser.
|
||||
|
||||
The docs are also automatically built when you submit a PR. The job that
|
||||
builds the docs is named `build_docs`. You can access the rendered docs by
|
||||
clicking on that job and then going to the "Artifacts" tab.
|
||||
|
||||
You can clean the built docs and re-start the build from scratch by doing ``make
|
||||
clean``.
|
||||
|
||||
#### Building the example gallery - or not
|
||||
|
||||
In most cases, running `make html-noplot` is enough to build the docs for your
|
||||
specific use-case. The `noplot` part tells sphinx **not** to build the examples
|
||||
in the [gallery](https://pytorch.org/vision/stable/auto_examples/index.html),
|
||||
which saves a lot of building time.
|
||||
|
||||
If you need to build all the examples in the gallery, then you can use `make
|
||||
html`.
|
||||
|
||||
You can also choose to only build a subset of the examples by using the
|
||||
``EXAMPLES_PATTERN`` env variable, which accepts a regular expression. For
|
||||
example ``EXAMPLES_PATTERN="transforms" make html`` will only build the examples
|
||||
with "transforms" in their name.
|
||||
|
||||
### New architecture or improved model weights
|
||||
|
||||
Please refer to the guidelines in [Contributing to Torchvision - Models](https://github.com/pytorch/vision/blob/main/CONTRIBUTING_MODELS.md).
|
||||
|
||||
### New dataset
|
||||
|
||||
Please, do not send any PR with a new dataset without discussing
|
||||
it in an issue as, most likely, it will not be accepted.
|
||||
|
||||
### Pull Request
|
||||
|
||||
If all previous checks (flake8, mypy, unit tests) are passing, please send a PR. Submitted PR will pass other tests on
|
||||
different operating systems, python versions and hardware.
|
||||
|
||||
For more details about pull requests workflow,
|
||||
please read [GitHub's guides](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request).
|
||||
|
||||
## License
|
||||
|
||||
By contributing to Torchvision, you agree that your contributions will be licensed
|
||||
under the LICENSE file in the root directory of this source tree.
|
||||
|
||||
Contributors are also required to [sign our Contributor License Agreement](https://code.facebook.com/cla).
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
# Contributing to Torchvision - Models
|
||||
|
||||
- [New Model Architectures - Overview](#new-model-architectures---overview)
|
||||
|
||||
- [New Weights for Existing Model Architectures](#new-weights-for-existing-model-architectures)
|
||||
|
||||
## New Model Architectures - Overview
|
||||
|
||||
For someone who would be interested in adding a model architecture, it is also expected to train the model, so here are a few important considerations:
|
||||
|
||||
- Training big models requires lots of resources and the cost quickly adds up
|
||||
|
||||
- Reproducing models is fun but also risky as you might not always get the results reported on the paper. It might require a huge amount of effort to close the gap
|
||||
|
||||
- The contribution might not get merged if we significantly lack in terms of accuracy, speed etc
|
||||
|
||||
- Including new models in TorchVision might not be the best approach, so other options such as releasing the model through to [Pytorch Hub](https://pytorch.org/hub/) should be considered
|
||||
|
||||
So, before starting any work and submitting a PR there are a few critical things that need to be taken into account in order to make sure the planned contribution is within the context of TorchVision, and the requirements and expectations are discussed beforehand. If this step is skipped and a PR is submitted without prior discussion it will almost certainly be rejected.
|
||||
|
||||
### 1. Preparation work
|
||||
|
||||
- Start by looking into this [issue](https://github.com/pytorch/vision/issues/2707) in order to have an idea of the models that are being considered, express your willingness to add a new model and discuss with the community whether this model should be included in TorchVision. It is very important at this stage to make sure that there is an agreement on the value of having this model in TorchVision and there is no one else already working on it.
|
||||
|
||||
- If the decision is to include the new model, then please create a new ticket which will be used for all design and implementation discussions prior to the PR. One of the TorchVision maintainers will reach out at this stage and this will be your POC from this point onwards in order to provide support, guidance and regular feedback.
|
||||
|
||||
### 2. Implement the model
|
||||
|
||||
Please take a look at existing models in TorchVision to get familiar with the idioms. Also, please look at recent contributions for new models. If in doubt about any design decisions you can ask for feedback on the issue created in step 1. Example of things to take into account:
|
||||
|
||||
- The implementation should be as close as possible to the canonical implementation/paper
|
||||
- The PR must include the code implementation, documentation and tests
|
||||
- It should also extend the existing reference scripts used to train the model
|
||||
- The weights need to reproduce closely the results of the paper in terms of accuracy, even though the final weights to be deployed will be those trained by the TorchVision maintainers
|
||||
- The PR description should include commands/configuration used to train the model, so that the TorchVision maintainers can easily run them to verify the implementation and generate the final model to be released
|
||||
- Make sure we re-use existing components as much as possible (inheritance)
|
||||
- New primitives (transforms, losses, etc.) can be added if necessary, but the final location will be determined after discussion with the dedicated maintainer
|
||||
- Please take a look at the detailed [implementation and documentation guidelines](https://github.com/pytorch/vision/issues/5319) for a fine grain list of things not to be missed
|
||||
|
||||
### 3. Train the model with reference scripts
|
||||
|
||||
To validate the new model against the common benchmark, as well as to generate pre-trained weights, you must use TorchVision’s reference scripts to train the model.
|
||||
|
||||
Make sure all logs and a final (or best) checkpoint are saved, because it is expected that a submission shows that a model has been successfully trained and the results are in line with the original paper/repository. This will allow the reviewers to quickly check the validity of the submission, but please note that the final model to be released will be re-trained by the maintainers in order to verify reproducibility, ensure that the changes occurred during the PR review did not introduce any bugs, and to avoid moving around a large amount of data (including all checkpoints and logs).
|
||||
|
||||
### 4. Submit a PR
|
||||
|
||||
Submit a PR and tag the assigned maintainer. This PR should:
|
||||
|
||||
- Link the original ticket
|
||||
- Provide a link for the original paper and the original repository if available
|
||||
- Highlight the important test metrics and how they compare to the original paper
|
||||
- Highlight any design choices that deviate from the original paper/implementation and rationale for these choices
|
||||
|
||||
## New Weights for Existing Model Architectures
|
||||
|
||||
The process of improving existing models, for instance improving accuracy by retraining the model with a different set of hyperparameters or augmentations, is the following:
|
||||
|
||||
1. Open a ticket and discuss with the community and maintainers whether this improvement should be added to TorchVision. Note that to add new weights the improvement should be significant.
|
||||
|
||||
2. Train the model using TorchVision reference scripts. You can add new primitives (transforms, losses, etc) when necessary, but the final location will be determined after discussion with the dedicated maintainer.
|
||||
|
||||
3. Open a PR with the new weights, together with the training logs and the checkpoint chosen so the reviewers can verify the submission. Details on how the model was trained, i.e., the training command using the reference scripts, should be included in the PR.
|
||||
|
||||
4. The PR reviewers should replicate the results on their side to verify the submission and if all goes well the new weights should be ready to be released!
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) Soumith Chintala 2016,
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
include README.md
|
||||
include LICENSE
|
||||
|
||||
recursive-exclude * __pycache__
|
||||
recursive-exclude * *.py[co]
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
# torchvision
|
||||
|
||||
[](https://pepy.tech/project/torchvision)
|
||||
[](https://pytorch.org/vision/stable/index.html)
|
||||
|
||||
The torchvision package consists of popular datasets, model architectures, and common image transformations for computer
|
||||
vision.
|
||||
|
||||
## Installation
|
||||
|
||||
Please refer to the [official
|
||||
instructions](https://pytorch.org/get-started/locally/) to install the stable
|
||||
versions of `torch` and `torchvision` on your system.
|
||||
|
||||
To build source, refer to our [contributing
|
||||
page](https://github.com/pytorch/vision/blob/main/CONTRIBUTING.md#development-installation).
|
||||
|
||||
The following is the corresponding `torchvision` versions and supported Python
|
||||
versions.
|
||||
|
||||
| `torch` | `torchvision` | Python |
|
||||
| ------------------ | ------------------ | ------------------- |
|
||||
| `main` / `nightly` | `main` / `nightly` | `>=3.9`, `<=3.12` |
|
||||
| `2.5` | `0.20` | `>=3.9`, `<=3.12` |
|
||||
| `2.4` | `0.19` | `>=3.8`, `<=3.12` |
|
||||
| `2.3` | `0.18` | `>=3.8`, `<=3.12` |
|
||||
| `2.2` | `0.17` | `>=3.8`, `<=3.11` |
|
||||
| `2.1` | `0.16` | `>=3.8`, `<=3.11` |
|
||||
| `2.0` | `0.15` | `>=3.8`, `<=3.11` |
|
||||
|
||||
<details>
|
||||
<summary>older versions</summary>
|
||||
|
||||
| `torch` | `torchvision` | Python |
|
||||
|---------|-------------------|---------------------------|
|
||||
| `1.13` | `0.14` | `>=3.7.2`, `<=3.10` |
|
||||
| `1.12` | `0.13` | `>=3.7`, `<=3.10` |
|
||||
| `1.11` | `0.12` | `>=3.7`, `<=3.10` |
|
||||
| `1.10` | `0.11` | `>=3.6`, `<=3.9` |
|
||||
| `1.9` | `0.10` | `>=3.6`, `<=3.9` |
|
||||
| `1.8` | `0.9` | `>=3.6`, `<=3.9` |
|
||||
| `1.7` | `0.8` | `>=3.6`, `<=3.9` |
|
||||
| `1.6` | `0.7` | `>=3.6`, `<=3.8` |
|
||||
| `1.5` | `0.6` | `>=3.5`, `<=3.8` |
|
||||
| `1.4` | `0.5` | `==2.7`, `>=3.5`, `<=3.8` |
|
||||
| `1.3` | `0.4.2` / `0.4.3` | `==2.7`, `>=3.5`, `<=3.7` |
|
||||
| `1.2` | `0.4.1` | `==2.7`, `>=3.5`, `<=3.7` |
|
||||
| `1.1` | `0.3` | `==2.7`, `>=3.5`, `<=3.7` |
|
||||
| `<=1.0` | `0.2` | `==2.7`, `>=3.5`, `<=3.7` |
|
||||
|
||||
</details>
|
||||
|
||||
## Image Backends
|
||||
|
||||
Torchvision currently supports the following image backends:
|
||||
|
||||
- torch tensors
|
||||
- PIL images:
|
||||
- [Pillow](https://python-pillow.org/)
|
||||
- [Pillow-SIMD](https://github.com/uploadcare/pillow-simd) - a **much faster** drop-in replacement for Pillow with SIMD.
|
||||
|
||||
Read more in in our [docs](https://pytorch.org/vision/stable/transforms.html).
|
||||
|
||||
## [UNSTABLE] Video Backend
|
||||
|
||||
Torchvision currently supports the following video backends:
|
||||
|
||||
- [pyav](https://github.com/PyAV-Org/PyAV) (default) - Pythonic binding for ffmpeg libraries.
|
||||
- video_reader - This needs ffmpeg to be installed and torchvision to be built from source. There shouldn't be any
|
||||
conflicting version of ffmpeg installed. Currently, this is only supported on Linux.
|
||||
|
||||
```
|
||||
conda install -c conda-forge 'ffmpeg<4.3'
|
||||
python setup.py install
|
||||
```
|
||||
|
||||
# Using the models on C++
|
||||
|
||||
Refer to [example/cpp](https://github.com/pytorch/vision/tree/main/examples/cpp).
|
||||
|
||||
**DISCLAIMER**: the `libtorchvision` library includes the torchvision
|
||||
custom ops as well as most of the C++ torchvision APIs. Those APIs do not come
|
||||
with any backward-compatibility guarantees and may change from one version to
|
||||
the next. Only the Python APIs are stable and with backward-compatibility
|
||||
guarantees. So, if you need stability within a C++ environment, your best bet is
|
||||
to export the Python APIs via torchscript.
|
||||
|
||||
## Documentation
|
||||
|
||||
You can find the API documentation on the pytorch website: <https://pytorch.org/vision/stable/index.html>
|
||||
|
||||
## Contributing
|
||||
|
||||
See the [CONTRIBUTING](CONTRIBUTING.md) file for how to help out.
|
||||
|
||||
## Disclaimer on Datasets
|
||||
|
||||
This is a utility library that downloads and prepares public datasets. We do not host or distribute these datasets,
|
||||
vouch for their quality or fairness, or claim that you have license to use the dataset. It is your responsibility to
|
||||
determine whether you have permission to use the dataset under the dataset's license.
|
||||
|
||||
If you're a dataset owner and wish to update any part of it (description, citation, etc.), or do not want your dataset
|
||||
to be included in this library, please get in touch through a GitHub issue. Thanks for your contribution to the ML
|
||||
community!
|
||||
|
||||
## Pre-trained Model License
|
||||
|
||||
The pre-trained models provided in this library may have their own licenses or terms and conditions derived from the
|
||||
dataset used for training. It is your responsibility to determine whether you have permission to use the models for your
|
||||
use case.
|
||||
|
||||
More specifically, SWAG models are released under the CC-BY-NC 4.0 license. See
|
||||
[SWAG LICENSE](https://github.com/facebookresearch/SWAG/blob/main/LICENSE) for additional details.
|
||||
|
||||
## Citing TorchVision
|
||||
|
||||
If you find TorchVision useful in your work, please consider citing the following BibTeX entry:
|
||||
|
||||
```bibtex
|
||||
@software{torchvision2016,
|
||||
title = {TorchVision: PyTorch's Computer Vision library},
|
||||
author = {TorchVision maintainers and contributors},
|
||||
year = 2016,
|
||||
journal = {GitHub repository},
|
||||
publisher = {GitHub},
|
||||
howpublished = {\url{https://github.com/pytorch/vision}}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
local.properties
|
||||
**/*.iml
|
||||
.gradle
|
||||
.idea/*
|
||||
.externalNativeBuild
|
||||
build
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
## Status
|
||||
|
||||
The Android demo of TorchVision is currently unmaintained, untested and likely out-of-date.
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
allprojects {
|
||||
buildscript {
|
||||
ext {
|
||||
minSdkVersion = 21
|
||||
targetSdkVersion = 28
|
||||
compileSdkVersion = 28
|
||||
buildToolsVersion = '28.0.3'
|
||||
|
||||
coreVersion = "1.2.0"
|
||||
extJUnitVersion = "1.1.1"
|
||||
runnerVersion = "1.2.0"
|
||||
rulesVersion = "1.2.0"
|
||||
junitVersion = "4.12"
|
||||
|
||||
androidSupportAppCompatV7Version = "28.0.0"
|
||||
fbjniJavaOnlyVersion = "0.0.3"
|
||||
soLoaderNativeLoaderVersion = "0.10.5"
|
||||
pytorchAndroidVersion = "1.12"
|
||||
}
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.2'
|
||||
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.14.2'
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
ext.deps = [
|
||||
jsr305: 'com.google.code.findbugs:jsr305:3.0.1',
|
||||
]
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
ABI_FILTERS=armeabi-v7a,arm64-v8a,x86,x86_64
|
||||
|
||||
VERSION_NAME=0.15.0-SNAPSHOT
|
||||
GROUP=org.pytorch
|
||||
MAVEN_GROUP=org.pytorch
|
||||
SONATYPE_STAGING_PROFILE=orgpytorch
|
||||
POM_URL=https://github.com/pytorch/vision/
|
||||
POM_SCM_URL=https://github.com/pytorch/vision.git
|
||||
POM_SCM_CONNECTION=scm:git:https://github.com/pytorch/vision
|
||||
POM_SCM_DEV_CONNECTION=scm:git:git@github.com:pytorch/vision.git
|
||||
POM_LICENSE_NAME=BSD 3-Clause
|
||||
POM_LICENSE_URL=https://github.com/pytorch/vision/blob/main/LICENSE
|
||||
POM_ISSUES_URL=https://github.com/pytorch/vision/issues
|
||||
POM_LICENSE_DIST=repo
|
||||
POM_DEVELOPER_ID=pytorch
|
||||
POM_DEVELOPER_NAME=pytorch
|
||||
|
||||
# Gradle internals
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
testAppAllVariantsEnabled=false
|
||||
|
||||
org.gradle.jvmargs=-Xmx12g
|
||||
BIN
cache/torch/hub/pytorch_vision_main/android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
cache/torch/hub/pytorch_vision_main/android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
cache/torch/hub/pytorch_vision_main/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
cache/torch/hub/pytorch_vision_main/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
11
cache/torch/hub/pytorch_vision_main/android/gradle_scripts/android_tasks.gradle
vendored
Normal file
11
cache/torch/hub/pytorch_vision_main/android/gradle_scripts/android_tasks.gradle
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
afterEvaluate { project ->
|
||||
if (POM_PACKAGING == 'aar') {
|
||||
task headersJar(type: Jar) {
|
||||
archiveClassifier.set('headers')
|
||||
from("$rootDir/cxx/") {
|
||||
include '**/*.h'
|
||||
}
|
||||
}
|
||||
artifacts.add('archives', headersJar)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
apply from: rootProject.file('gradle_scripts/android_tasks.gradle')
|
||||
|
||||
apply plugin: 'com.vanniktech.maven.publish'
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
cmake_minimum_required(VERSION 3.4.1)
|
||||
set(TARGET torchvision_ops)
|
||||
project(${TARGET} CXX)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
string(APPEND CMAKE_CXX_FLAGS " -DMOBILE")
|
||||
|
||||
set(build_DIR ${CMAKE_SOURCE_DIR}/build)
|
||||
set(root_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
|
||||
|
||||
file(GLOB VISION_SRCS
|
||||
../../torchvision/csrc/ops/cpu/*.h
|
||||
../../torchvision/csrc/ops/cpu/*.cpp
|
||||
../../torchvision/csrc/ops/*.h
|
||||
../../torchvision/csrc/ops/*.cpp)
|
||||
|
||||
add_library(${TARGET} SHARED
|
||||
${VISION_SRCS}
|
||||
)
|
||||
|
||||
file(GLOB PYTORCH_INCLUDE_DIRS "${build_DIR}/pytorch_android*.aar/headers")
|
||||
file(GLOB PYTORCH_INCLUDE_DIRS_CSRC "${build_DIR}/pytorch_android*.aar/headers/torch/csrc/api/include")
|
||||
file(GLOB PYTORCH_LINK_DIRS "${build_DIR}/pytorch_android*.aar/jni/${ANDROID_ABI}")
|
||||
|
||||
target_compile_options(${TARGET} PRIVATE
|
||||
-fexceptions
|
||||
)
|
||||
|
||||
set(BUILD_SUBDIR ${ANDROID_ABI})
|
||||
|
||||
find_library(PYTORCH_LIBRARY pytorch_jni
|
||||
PATHS ${PYTORCH_LINK_DIRS}
|
||||
NO_CMAKE_FIND_ROOT_PATH)
|
||||
|
||||
find_library(FBJNI_LIBRARY fbjni
|
||||
PATHS ${PYTORCH_LINK_DIRS}
|
||||
NO_CMAKE_FIND_ROOT_PATH)
|
||||
|
||||
target_include_directories(${TARGET} PRIVATE
|
||||
${PYTORCH_INCLUDE_DIRS}
|
||||
${PYTORCH_INCLUDE_DIRS_CSRC}
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET} PRIVATE
|
||||
${PYTORCH_LIBRARY}
|
||||
${FBJNI_LIBRARY}
|
||||
)
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'maven'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url "https://oss.sonatype.org/content/repositories/snapshots"
|
||||
}
|
||||
flatDir {
|
||||
dirs 'aars'
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
configurations {
|
||||
extractForNativeBuild
|
||||
}
|
||||
compileSdkVersion rootProject.compileSdkVersion
|
||||
buildToolsVersion rootProject.buildToolsVersion
|
||||
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.minSdkVersion
|
||||
targetSdkVersion rootProject.targetSdkVersion
|
||||
versionCode 0
|
||||
versionName "0.1"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
ndk {
|
||||
abiFilters ABI_FILTERS.split(",")
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
minifyEnabled false
|
||||
debuggable true
|
||||
}
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
|
||||
useLibrary 'android.test.runner'
|
||||
useLibrary 'android.test.base'
|
||||
useLibrary 'android.test.mock'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.android.support:appcompat-v7:' + rootProject.androidSupportAppCompatV7Version
|
||||
|
||||
extractForNativeBuild "org.pytorch:pytorch_android:$pytorchAndroidVersion"
|
||||
|
||||
// For testing: deps on local aar files
|
||||
//implementation(name: 'pytorch_android-release', ext: 'aar')
|
||||
//extractForNativeBuild(name: 'pytorch_android-release', ext: 'aar')
|
||||
//implementation 'com.facebook.fbjni:fbjni-java-only:0.0.3'
|
||||
}
|
||||
|
||||
task extractAARForNativeBuild {
|
||||
doLast {
|
||||
configurations.extractForNativeBuild.files.each {
|
||||
def file = it.absoluteFile
|
||||
copy {
|
||||
from zipTree(file)
|
||||
into "$buildDir/$file.name"
|
||||
include "headers/**"
|
||||
include "jni/**"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.whenTaskAdded { task ->
|
||||
if (task.name.contains('externalNativeBuild')) {
|
||||
task.dependsOn(extractAARForNativeBuild)
|
||||
}
|
||||
}
|
||||
|
||||
apply from: rootProject.file('gradle_scripts/release.gradle')
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
classifier = 'sources'
|
||||
}
|
||||
|
||||
artifacts.add('archives', sourcesJar)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
POM_NAME=torchvision ops
|
||||
POM_DESCRIPTION=torchvision ops
|
||||
POM_ARTIFACT_ID=torchvision_ops
|
||||
POM_PACKAGING=aar
|
||||
|
|
@ -0,0 +1 @@
|
|||
<manifest package="org.pytorch.torchvision.ops" />
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
include ':ops', ':test_app'
|
||||
|
||||
project(':ops').projectDir = file('ops')
|
||||
project(':test_app').projectDir = file('test_app/app')
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url "https://oss.sonatype.org/content/repositories/snapshots"
|
||||
}
|
||||
flatDir {
|
||||
dirs 'aars'
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
configurations {
|
||||
extractForNativeBuild
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility 1.8
|
||||
targetCompatibility 1.8
|
||||
}
|
||||
compileSdkVersion rootProject.compileSdkVersion
|
||||
buildToolsVersion rootProject.buildToolsVersion
|
||||
defaultConfig {
|
||||
applicationId "org.pytorch.testapp"
|
||||
minSdkVersion rootProject.minSdkVersion
|
||||
targetSdkVersion rootProject.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
ndk {
|
||||
abiFilters ABI_FILTERS.split(",")
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
abiFilters ABI_FILTERS.split(",")
|
||||
arguments "-DANDROID_STL=c++_shared"
|
||||
}
|
||||
}
|
||||
buildConfigField("String", "MODULE_ASSET_NAME", "\"frcnn_mnetv3.pt\"")
|
||||
buildConfigField("String", "LOGCAT_TAG", "@string/app_name")
|
||||
buildConfigField("long[]", "INPUT_TENSOR_SHAPE", "new long[]{3, 96, 96}")
|
||||
addManifestPlaceholders([APP_NAME: "@string/app_name", MAIN_ACTIVITY: "org.pytorch.testapp.MainActivity"])
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
minifyEnabled false
|
||||
debuggable true
|
||||
}
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
flavorDimensions "model", "activity", "build"
|
||||
productFlavors {
|
||||
frcnnMnetv3 {
|
||||
dimension "model"
|
||||
applicationIdSuffix ".frcnnMnetv3"
|
||||
buildConfigField("String", "MODULE_ASSET_NAME", "\"frcnn_mnetv3.pt\"")
|
||||
addManifestPlaceholders([APP_NAME: "TV_FRCNN_MNETV3"])
|
||||
buildConfigField("String", "LOGCAT_TAG", "\"pytorch-frcnn-mnetv3\"")
|
||||
}
|
||||
camera {
|
||||
dimension "activity"
|
||||
addManifestPlaceholders([APP_NAME: "TV_CAMERA_FRCNN"])
|
||||
addManifestPlaceholders([MAIN_ACTIVITY: "org.pytorch.testapp.CameraActivity"])
|
||||
}
|
||||
base {
|
||||
dimension "activity"
|
||||
}
|
||||
aar {
|
||||
dimension "build"
|
||||
}
|
||||
local {
|
||||
dimension "build"
|
||||
}
|
||||
}
|
||||
packagingOptions {
|
||||
doNotStrip '**.so'
|
||||
pickFirst '**.so'
|
||||
}
|
||||
|
||||
// Filtering for CI
|
||||
if (!testAppAllVariantsEnabled.toBoolean()) {
|
||||
variantFilter { variant ->
|
||||
def names = variant.flavors*.name
|
||||
if (names.contains("aar")) {
|
||||
setIgnore(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.all { task ->
|
||||
// Disable externalNativeBuild for all but nativeBuild variant
|
||||
if (task.name.startsWith('externalNativeBuild')
|
||||
&& !task.name.contains('NativeBuild')) {
|
||||
task.enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
implementation 'com.facebook.soloader:nativeloader:0.8.0'
|
||||
localImplementation project(':ops')
|
||||
|
||||
implementation "org.pytorch:pytorch_android:$pytorchAndroidVersion"
|
||||
implementation "org.pytorch:pytorch_android_torchvision:$pytorchAndroidVersion"
|
||||
|
||||
aarImplementation(name: 'pytorch_android-release', ext: 'aar')
|
||||
aarImplementation(name: 'pytorch_android_torchvision-release', ext: 'aar')
|
||||
|
||||
def camerax_version = "1.0.0-alpha05"
|
||||
implementation "androidx.camera:camera-core:$camerax_version"
|
||||
implementation "androidx.camera:camera-camera2:$camerax_version"
|
||||
implementation 'com.google.android.material:material:1.0.0-beta01'
|
||||
}
|
||||
|
||||
task extractAARForNativeBuild {
|
||||
doLast {
|
||||
configurations.extractForNativeBuild.files.each {
|
||||
def file = it.absoluteFile
|
||||
copy {
|
||||
from zipTree(file)
|
||||
into "$buildDir/$file.name"
|
||||
include "headers/**"
|
||||
include "jni/**"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.whenTaskAdded { task ->
|
||||
if (task.name.contains('externalNativeBuild')) {
|
||||
task.dependsOn(extractAARForNativeBuild)
|
||||
}
|
||||
}
|
||||
21
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/AndroidManifest.xml
vendored
Normal file
21
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/AndroidManifest.xml
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.pytorch.testapp">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:label="${APP_NAME}"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<activity android:name="${MAIN_ACTIVITY}">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package org.pytorch.testapp;
|
||||
|
||||
class BBox {
|
||||
public final float score;
|
||||
public final float x0;
|
||||
public final float y0;
|
||||
public final float x1;
|
||||
public final float y1;
|
||||
|
||||
public BBox(float score, float x0, float y0, float x1, float y1) {
|
||||
this.score = score;
|
||||
this.x0 = x0;
|
||||
this.y0 = y0;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Box{score=%f x0=%f y0=%f x1=%f y1=%f", score, x0, y0, x1, y1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,432 @@
|
|||
package org.pytorch.testapp;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.SystemClock;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.view.TextureView;
|
||||
import android.view.ViewStub;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.camera.core.CameraX;
|
||||
import androidx.camera.core.ImageAnalysis;
|
||||
import androidx.camera.core.ImageAnalysisConfig;
|
||||
import androidx.camera.core.ImageProxy;
|
||||
import androidx.camera.core.Preview;
|
||||
import androidx.camera.core.PreviewConfig;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import com.facebook.soloader.nativeloader.NativeLoader;
|
||||
import com.facebook.soloader.nativeloader.SystemDelegate;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.pytorch.IValue;
|
||||
import org.pytorch.Module;
|
||||
import org.pytorch.Tensor;
|
||||
|
||||
public class CameraActivity extends AppCompatActivity {
|
||||
|
||||
private static final float BBOX_SCORE_DRAW_THRESHOLD = 0.5f;
|
||||
private static final String TAG = BuildConfig.LOGCAT_TAG;
|
||||
private static final int TEXT_TRIM_SIZE = 4096;
|
||||
private static final int RGB_MAX_CHANNEL_VALUE = 262143;
|
||||
|
||||
private static final int REQUEST_CODE_CAMERA_PERMISSION = 200;
|
||||
private static final String[] PERMISSIONS = {Manifest.permission.CAMERA};
|
||||
|
||||
static {
|
||||
if (!NativeLoader.isInitialized()) {
|
||||
NativeLoader.init(new SystemDelegate());
|
||||
}
|
||||
NativeLoader.loadLibrary("pytorch_jni");
|
||||
NativeLoader.loadLibrary("torchvision_ops");
|
||||
}
|
||||
|
||||
private Bitmap mInputTensorBitmap;
|
||||
private Bitmap mBitmap;
|
||||
private Canvas mCanvas;
|
||||
|
||||
private long mLastAnalysisResultTime;
|
||||
|
||||
protected HandlerThread mBackgroundThread;
|
||||
protected Handler mBackgroundHandler;
|
||||
protected Handler mUIHandler;
|
||||
|
||||
private TextView mTextView;
|
||||
private ImageView mCameraOverlay;
|
||||
private StringBuilder mTextViewStringBuilder = new StringBuilder();
|
||||
|
||||
private Paint mBboxPaint;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_camera);
|
||||
mTextView = findViewById(R.id.text);
|
||||
mCameraOverlay = findViewById(R.id.camera_overlay);
|
||||
mUIHandler = new Handler(getMainLooper());
|
||||
startBackgroundThread();
|
||||
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_CODE_CAMERA_PERMISSION);
|
||||
} else {
|
||||
setupCameraX();
|
||||
}
|
||||
mBboxPaint = new Paint();
|
||||
mBboxPaint.setAntiAlias(true);
|
||||
mBboxPaint.setDither(true);
|
||||
mBboxPaint.setColor(Color.GREEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
startBackgroundThread();
|
||||
}
|
||||
|
||||
protected void startBackgroundThread() {
|
||||
mBackgroundThread = new HandlerThread("ModuleActivity");
|
||||
mBackgroundThread.start();
|
||||
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
stopBackgroundThread();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
protected void stopBackgroundThread() {
|
||||
mBackgroundThread.quitSafely();
|
||||
try {
|
||||
mBackgroundThread.join();
|
||||
mBackgroundThread = null;
|
||||
mBackgroundHandler = null;
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "Error on stopping background thread", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(
|
||||
int requestCode, String[] permissions, int[] grantResults) {
|
||||
if (requestCode == REQUEST_CODE_CAMERA_PERMISSION) {
|
||||
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
"You can't use image classification example without granting CAMERA permission",
|
||||
Toast.LENGTH_LONG)
|
||||
.show();
|
||||
finish();
|
||||
} else {
|
||||
setupCameraX();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setupCameraX() {
|
||||
final TextureView textureView =
|
||||
((ViewStub) findViewById(R.id.camera_texture_view_stub))
|
||||
.inflate()
|
||||
.findViewById(R.id.texture_view);
|
||||
final PreviewConfig previewConfig = new PreviewConfig.Builder().build();
|
||||
final Preview preview = new Preview(previewConfig);
|
||||
preview.setOnPreviewOutputUpdateListener(
|
||||
new Preview.OnPreviewOutputUpdateListener() {
|
||||
@Override
|
||||
public void onUpdated(Preview.PreviewOutput output) {
|
||||
textureView.setSurfaceTexture(output.getSurfaceTexture());
|
||||
}
|
||||
});
|
||||
|
||||
final DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||
|
||||
final ImageAnalysisConfig imageAnalysisConfig =
|
||||
new ImageAnalysisConfig.Builder()
|
||||
.setTargetResolution(new Size(displayMetrics.widthPixels, displayMetrics.heightPixels))
|
||||
.setCallbackHandler(mBackgroundHandler)
|
||||
.setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
|
||||
.build();
|
||||
final ImageAnalysis imageAnalysis = new ImageAnalysis(imageAnalysisConfig);
|
||||
imageAnalysis.setAnalyzer(
|
||||
new ImageAnalysis.Analyzer() {
|
||||
@Override
|
||||
public void analyze(ImageProxy image, int rotationDegrees) {
|
||||
if (SystemClock.elapsedRealtime() - mLastAnalysisResultTime < 500) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Result result = CameraActivity.this.analyzeImage(image, rotationDegrees);
|
||||
|
||||
if (result != null) {
|
||||
mLastAnalysisResultTime = SystemClock.elapsedRealtime();
|
||||
CameraActivity.this.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CameraActivity.this.handleResult(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CameraX.bindToLifecycle(this, preview, imageAnalysis);
|
||||
}
|
||||
|
||||
private Module mModule;
|
||||
private FloatBuffer mInputTensorBuffer;
|
||||
private Tensor mInputTensor;
|
||||
|
||||
private static int clamp0255(int x) {
|
||||
if (x > 255) {
|
||||
return 255;
|
||||
}
|
||||
return x < 0 ? 0 : x;
|
||||
}
|
||||
|
||||
protected void fillInputTensorBuffer(
|
||||
ImageProxy image, int rotationDegrees, FloatBuffer inputTensorBuffer) {
|
||||
|
||||
if (mInputTensorBitmap == null) {
|
||||
final int tensorSize = Math.min(image.getWidth(), image.getHeight());
|
||||
mInputTensorBitmap = Bitmap.createBitmap(tensorSize, tensorSize, Bitmap.Config.ARGB_8888);
|
||||
}
|
||||
|
||||
ImageProxy.PlaneProxy[] planes = image.getPlanes();
|
||||
ImageProxy.PlaneProxy Y = planes[0];
|
||||
ImageProxy.PlaneProxy U = planes[1];
|
||||
ImageProxy.PlaneProxy V = planes[2];
|
||||
ByteBuffer yBuffer = Y.getBuffer();
|
||||
ByteBuffer uBuffer = U.getBuffer();
|
||||
ByteBuffer vBuffer = V.getBuffer();
|
||||
final int imageWidth = image.getWidth();
|
||||
final int imageHeight = image.getHeight();
|
||||
final int tensorSize = Math.min(imageWidth, imageHeight);
|
||||
|
||||
int widthAfterRtn = imageWidth;
|
||||
int heightAfterRtn = imageHeight;
|
||||
boolean oddRotation = rotationDegrees == 90 || rotationDegrees == 270;
|
||||
if (oddRotation) {
|
||||
widthAfterRtn = imageHeight;
|
||||
heightAfterRtn = imageWidth;
|
||||
}
|
||||
|
||||
int minSizeAfterRtn = Math.min(heightAfterRtn, widthAfterRtn);
|
||||
int cropWidthAfterRtn = minSizeAfterRtn;
|
||||
int cropHeightAfterRtn = minSizeAfterRtn;
|
||||
|
||||
int cropWidthBeforeRtn = cropWidthAfterRtn;
|
||||
int cropHeightBeforeRtn = cropHeightAfterRtn;
|
||||
if (oddRotation) {
|
||||
cropWidthBeforeRtn = cropHeightAfterRtn;
|
||||
cropHeightBeforeRtn = cropWidthAfterRtn;
|
||||
}
|
||||
|
||||
int offsetX = (int) ((imageWidth - cropWidthBeforeRtn) / 2.f);
|
||||
int offsetY = (int) ((imageHeight - cropHeightBeforeRtn) / 2.f);
|
||||
|
||||
int yRowStride = Y.getRowStride();
|
||||
int yPixelStride = Y.getPixelStride();
|
||||
int uvRowStride = U.getRowStride();
|
||||
int uvPixelStride = U.getPixelStride();
|
||||
|
||||
float scale = cropWidthAfterRtn / tensorSize;
|
||||
int yIdx, uvIdx, yi, ui, vi;
|
||||
final int channelSize = tensorSize * tensorSize;
|
||||
for (int y = 0; y < tensorSize; y++) {
|
||||
for (int x = 0; x < tensorSize; x++) {
|
||||
final int centerCropX = (int) Math.floor(x * scale);
|
||||
final int centerCropY = (int) Math.floor(y * scale);
|
||||
int srcX = centerCropX + offsetX;
|
||||
int srcY = centerCropY + offsetY;
|
||||
|
||||
if (rotationDegrees == 90) {
|
||||
srcX = offsetX + centerCropY;
|
||||
srcY = offsetY + (minSizeAfterRtn - 1) - centerCropX;
|
||||
} else if (rotationDegrees == 180) {
|
||||
srcX = offsetX + (minSizeAfterRtn - 1) - centerCropX;
|
||||
srcY = offsetY + (minSizeAfterRtn - 1) - centerCropY;
|
||||
} else if (rotationDegrees == 270) {
|
||||
srcX = offsetX + (minSizeAfterRtn - 1) - centerCropY;
|
||||
srcY = offsetY + centerCropX;
|
||||
}
|
||||
|
||||
yIdx = srcY * yRowStride + srcX * yPixelStride;
|
||||
uvIdx = (srcY >> 1) * uvRowStride + (srcX >> 1) * uvPixelStride;
|
||||
|
||||
yi = yBuffer.get(yIdx) & 0xff;
|
||||
ui = uBuffer.get(uvIdx) & 0xff;
|
||||
vi = vBuffer.get(uvIdx) & 0xff;
|
||||
|
||||
yi = (yi - 16) < 0 ? 0 : (yi - 16);
|
||||
ui -= 128;
|
||||
vi -= 128;
|
||||
|
||||
int a0 = 1192 * yi;
|
||||
int ri = (a0 + 1634 * vi);
|
||||
int gi = (a0 - 833 * vi - 400 * ui);
|
||||
int bi = (a0 + 2066 * ui);
|
||||
|
||||
ri = ri > RGB_MAX_CHANNEL_VALUE ? RGB_MAX_CHANNEL_VALUE : (ri < 0 ? 0 : ri);
|
||||
gi = gi > RGB_MAX_CHANNEL_VALUE ? RGB_MAX_CHANNEL_VALUE : (gi < 0 ? 0 : gi);
|
||||
bi = bi > RGB_MAX_CHANNEL_VALUE ? RGB_MAX_CHANNEL_VALUE : (bi < 0 ? 0 : bi);
|
||||
|
||||
final int color =
|
||||
0xff000000 | ((ri << 6) & 0xff0000) | ((gi >> 2) & 0xff00) | ((bi >> 10) & 0xff);
|
||||
mInputTensorBitmap.setPixel(x, y, color);
|
||||
inputTensorBuffer.put(0 * channelSize + y * tensorSize + x, clamp0255(ri >> 10) / 255.f);
|
||||
inputTensorBuffer.put(1 * channelSize + y * tensorSize + x, clamp0255(gi >> 10) / 255.f);
|
||||
inputTensorBuffer.put(2 * channelSize + y * tensorSize + x, clamp0255(bi >> 10) / 255.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String assetFilePath(Context context, String assetName) {
|
||||
File file = new File(context.getFilesDir(), assetName);
|
||||
if (file.exists() && file.length() > 0) {
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
try (InputStream is = context.getAssets().open(assetName)) {
|
||||
try (OutputStream os = new FileOutputStream(file)) {
|
||||
byte[] buffer = new byte[4 * 1024];
|
||||
int read;
|
||||
while ((read = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, read);
|
||||
}
|
||||
os.flush();
|
||||
}
|
||||
return file.getAbsolutePath();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Error process asset " + assetName + " to file path");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@Nullable
|
||||
protected Result analyzeImage(ImageProxy image, int rotationDegrees) {
|
||||
Log.i(TAG, String.format("analyzeImage(%s, %d)", image, rotationDegrees));
|
||||
final int tensorSize = Math.min(image.getWidth(), image.getHeight());
|
||||
if (mModule == null) {
|
||||
Log.i(TAG, "Loading module from asset '" + BuildConfig.MODULE_ASSET_NAME + "'");
|
||||
mInputTensorBuffer = Tensor.allocateFloatBuffer(3 * tensorSize * tensorSize);
|
||||
mInputTensor = Tensor.fromBlob(mInputTensorBuffer, new long[] {3, tensorSize, tensorSize});
|
||||
final String modelFileAbsoluteFilePath =
|
||||
new File(assetFilePath(this, BuildConfig.MODULE_ASSET_NAME)).getAbsolutePath();
|
||||
mModule = Module.load(modelFileAbsoluteFilePath);
|
||||
}
|
||||
|
||||
final long startTime = SystemClock.elapsedRealtime();
|
||||
fillInputTensorBuffer(image, rotationDegrees, mInputTensorBuffer);
|
||||
|
||||
final long moduleForwardStartTime = SystemClock.elapsedRealtime();
|
||||
final IValue outputTuple = mModule.forward(IValue.listFrom(mInputTensor));
|
||||
final IValue out1 = outputTuple.toTuple()[1];
|
||||
final Map<String, IValue> map = out1.toList()[0].toDictStringKey();
|
||||
|
||||
float[] boxesData = new float[] {};
|
||||
float[] scoresData = new float[] {};
|
||||
final List<BBox> bboxes = new ArrayList<>();
|
||||
if (map.containsKey("boxes")) {
|
||||
final Tensor boxesTensor = map.get("boxes").toTensor();
|
||||
final Tensor scoresTensor = map.get("scores").toTensor();
|
||||
boxesData = boxesTensor.getDataAsFloatArray();
|
||||
scoresData = scoresTensor.getDataAsFloatArray();
|
||||
final int n = scoresData.length;
|
||||
for (int i = 0; i < n; i++) {
|
||||
final BBox bbox =
|
||||
new BBox(
|
||||
scoresData[i],
|
||||
boxesData[4 * i + 0],
|
||||
boxesData[4 * i + 1],
|
||||
boxesData[4 * i + 2],
|
||||
boxesData[4 * i + 3]);
|
||||
android.util.Log.i(TAG, String.format("Forward result %d: %s", i, bbox));
|
||||
bboxes.add(bbox);
|
||||
}
|
||||
} else {
|
||||
android.util.Log.i(TAG, "Forward result empty");
|
||||
}
|
||||
|
||||
final long moduleForwardDuration = SystemClock.elapsedRealtime() - moduleForwardStartTime;
|
||||
final long analysisDuration = SystemClock.elapsedRealtime() - startTime;
|
||||
return new Result(tensorSize, bboxes, moduleForwardDuration, analysisDuration);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
protected void handleResult(Result result) {
|
||||
final int W = mCameraOverlay.getMeasuredWidth();
|
||||
final int H = mCameraOverlay.getMeasuredHeight();
|
||||
|
||||
final int size = Math.min(W, H);
|
||||
final int offsetX = (W - size) / 2;
|
||||
final int offsetY = (H - size) / 2;
|
||||
|
||||
float scaleX = (float) size / result.tensorSize;
|
||||
float scaleY = (float) size / result.tensorSize;
|
||||
if (mBitmap == null) {
|
||||
mBitmap = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888);
|
||||
mCanvas = new Canvas(mBitmap);
|
||||
}
|
||||
|
||||
mCanvas.drawBitmap(
|
||||
mInputTensorBitmap,
|
||||
new Rect(0, 0, result.tensorSize, result.tensorSize),
|
||||
new Rect(offsetX, offsetY, offsetX + size, offsetY + size),
|
||||
null);
|
||||
|
||||
for (final BBox bbox : result.bboxes) {
|
||||
if (bbox.score < BBOX_SCORE_DRAW_THRESHOLD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float c_x0 = offsetX + scaleX * bbox.x0;
|
||||
float c_y0 = offsetY + scaleY * bbox.y0;
|
||||
|
||||
float c_x1 = offsetX + scaleX * bbox.x1;
|
||||
float c_y1 = offsetY + scaleY * bbox.y1;
|
||||
|
||||
mCanvas.drawLine(c_x0, c_y0, c_x1, c_y0, mBboxPaint);
|
||||
mCanvas.drawLine(c_x1, c_y0, c_x1, c_y1, mBboxPaint);
|
||||
mCanvas.drawLine(c_x1, c_y1, c_x0, c_y1, mBboxPaint);
|
||||
mCanvas.drawLine(c_x0, c_y1, c_x0, c_y0, mBboxPaint);
|
||||
mCanvas.drawText(String.format("%.2f", bbox.score), c_x0, c_y0, mBboxPaint);
|
||||
}
|
||||
mCameraOverlay.setImageBitmap(mBitmap);
|
||||
|
||||
String message = String.format("forwardDuration:%d", result.moduleForwardDuration);
|
||||
Log.i(TAG, message);
|
||||
mTextViewStringBuilder.insert(0, '\n').insert(0, message);
|
||||
if (mTextViewStringBuilder.length() > TEXT_TRIM_SIZE) {
|
||||
mTextViewStringBuilder.delete(TEXT_TRIM_SIZE, mTextViewStringBuilder.length());
|
||||
}
|
||||
mTextView.setText(mTextViewStringBuilder.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
package org.pytorch.testapp;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.facebook.soloader.nativeloader.NativeLoader;
|
||||
import com.facebook.soloader.nativeloader.SystemDelegate;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.Map;
|
||||
import org.pytorch.IValue;
|
||||
import org.pytorch.Module;
|
||||
import org.pytorch.PyTorchAndroid;
|
||||
import org.pytorch.Tensor;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
static {
|
||||
if (!NativeLoader.isInitialized()) {
|
||||
NativeLoader.init(new SystemDelegate());
|
||||
}
|
||||
NativeLoader.loadLibrary("pytorch_jni");
|
||||
NativeLoader.loadLibrary("torchvision_ops");
|
||||
}
|
||||
|
||||
private static final String TAG = BuildConfig.LOGCAT_TAG;
|
||||
private static final int TEXT_TRIM_SIZE = 4096;
|
||||
|
||||
private TextView mTextView;
|
||||
|
||||
protected HandlerThread mBackgroundThread;
|
||||
protected Handler mBackgroundHandler;
|
||||
private Module mModule;
|
||||
private FloatBuffer mInputTensorBuffer;
|
||||
private Tensor mInputTensor;
|
||||
private StringBuilder mTextViewStringBuilder = new StringBuilder();
|
||||
|
||||
private final Runnable mModuleForwardRunnable =
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Result result = doModuleForward();
|
||||
runOnUiThread(
|
||||
() -> {
|
||||
handleResult(result);
|
||||
if (mBackgroundHandler != null) {
|
||||
mBackgroundHandler.post(mModuleForwardRunnable);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
mTextView = findViewById(R.id.text);
|
||||
startBackgroundThread();
|
||||
mBackgroundHandler.post(mModuleForwardRunnable);
|
||||
}
|
||||
|
||||
protected void startBackgroundThread() {
|
||||
mBackgroundThread = new HandlerThread(TAG + "_bg");
|
||||
mBackgroundThread.start();
|
||||
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
stopBackgroundThread();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
protected void stopBackgroundThread() {
|
||||
mBackgroundThread.quitSafely();
|
||||
try {
|
||||
mBackgroundThread.join();
|
||||
mBackgroundThread = null;
|
||||
mBackgroundHandler = null;
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "Error stopping background thread", e);
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@Nullable
|
||||
protected Result doModuleForward() {
|
||||
if (mModule == null) {
|
||||
final long[] shape = BuildConfig.INPUT_TENSOR_SHAPE;
|
||||
long numElements = 1;
|
||||
for (int i = 0; i < shape.length; i++) {
|
||||
numElements *= shape[i];
|
||||
}
|
||||
mInputTensorBuffer = Tensor.allocateFloatBuffer((int) numElements);
|
||||
mInputTensor = Tensor.fromBlob(mInputTensorBuffer, BuildConfig.INPUT_TENSOR_SHAPE);
|
||||
PyTorchAndroid.setNumThreads(1);
|
||||
mModule = PyTorchAndroid.loadModuleFromAsset(getAssets(), BuildConfig.MODULE_ASSET_NAME);
|
||||
}
|
||||
|
||||
final long startTime = SystemClock.elapsedRealtime();
|
||||
final long moduleForwardStartTime = SystemClock.elapsedRealtime();
|
||||
final IValue outputTuple = mModule.forward(IValue.listFrom(mInputTensor));
|
||||
final IValue[] outputArray = outputTuple.toTuple();
|
||||
final IValue out0 = outputArray[0];
|
||||
final Map<String, IValue> map = out0.toDictStringKey();
|
||||
if (map.containsKey("boxes")) {
|
||||
final Tensor boxes = map.get("boxes").toTensor();
|
||||
final Tensor scores = map.get("scores").toTensor();
|
||||
final float[] boxesData = boxes.getDataAsFloatArray();
|
||||
final float[] scoresData = scores.getDataAsFloatArray();
|
||||
final int n = scoresData.length;
|
||||
for (int i = 0; i < n; i++) {
|
||||
android.util.Log.i(
|
||||
TAG,
|
||||
String.format(
|
||||
"Forward result %d: score %f box:(%f, %f, %f, %f)",
|
||||
scoresData[i],
|
||||
boxesData[4 * i + 0],
|
||||
boxesData[4 * i + 1],
|
||||
boxesData[4 * i + 2],
|
||||
boxesData[4 * i + 3]));
|
||||
}
|
||||
} else {
|
||||
android.util.Log.i(TAG, "Forward result empty");
|
||||
}
|
||||
|
||||
final long moduleForwardDuration = SystemClock.elapsedRealtime() - moduleForwardStartTime;
|
||||
final long analysisDuration = SystemClock.elapsedRealtime() - startTime;
|
||||
return new Result(new float[] {}, moduleForwardDuration, analysisDuration);
|
||||
}
|
||||
|
||||
static class Result {
|
||||
|
||||
private final float[] scores;
|
||||
private final long totalDuration;
|
||||
private final long moduleForwardDuration;
|
||||
|
||||
public Result(float[] scores, long moduleForwardDuration, long totalDuration) {
|
||||
this.scores = scores;
|
||||
this.moduleForwardDuration = moduleForwardDuration;
|
||||
this.totalDuration = totalDuration;
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
protected void handleResult(Result result) {
|
||||
String message = String.format("forwardDuration:%d", result.moduleForwardDuration);
|
||||
mTextViewStringBuilder.insert(0, '\n').insert(0, message);
|
||||
if (mTextViewStringBuilder.length() > TEXT_TRIM_SIZE) {
|
||||
mTextViewStringBuilder.delete(TEXT_TRIM_SIZE, mTextViewStringBuilder.length());
|
||||
}
|
||||
mTextView.setText(mTextViewStringBuilder.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package org.pytorch.testapp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class Result {
|
||||
public final int tensorSize;
|
||||
public final List<BBox> bboxes;
|
||||
public final long totalDuration;
|
||||
public final long moduleForwardDuration;
|
||||
|
||||
public Result(int tensorSize, List<BBox> bboxes, long moduleForwardDuration, long totalDuration) {
|
||||
this.tensorSize = tensorSize;
|
||||
this.bboxes = bboxes;
|
||||
this.moduleForwardDuration = moduleForwardDuration;
|
||||
this.totalDuration = totalDuration;
|
||||
}
|
||||
}
|
||||
28
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/layout/activity_camera.xml
vendored
Normal file
28
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/layout/activity_camera.xml
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".CameraActivity">
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/camera_texture_view_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout="@layout/texture_view"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="top"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#ff0000"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/camera_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</FrameLayout>
|
||||
17
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/layout/activity_main.xml
vendored
Normal file
17
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/layout/activity_main.xml
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="top"
|
||||
android:textSize="14sp"
|
||||
android:background="@android:color/black"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
</FrameLayout>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextureView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/texture_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp" />
|
||||
BIN
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/mipmap-mdpi/ic_launcher.png
vendored
Normal file
BIN
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/mipmap-mdpi/ic_launcher.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
6
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/values/colors.xml
vendored
Normal file
6
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/values/colors.xml
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#008577</color>
|
||||
<color name="colorPrimaryDark">#00574B</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
</resources>
|
||||
3
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/values/strings.xml
vendored
Normal file
3
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/values/strings.xml
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">TV_FRCNN</string>
|
||||
</resources>
|
||||
11
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/values/styles.xml
vendored
Normal file
11
cache/torch/hub/pytorch_vision_main/android/test_app/app/src/main/res/values/styles.xml
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import torch
|
||||
from torch.utils.mobile_optimizer import optimize_for_mobile
|
||||
from torchvision.models.detection import (
|
||||
fasterrcnn_mobilenet_v3_large_320_fpn,
|
||||
FasterRCNN_MobileNet_V3_Large_320_FPN_Weights,
|
||||
)
|
||||
|
||||
print(torch.__version__)
|
||||
|
||||
model = fasterrcnn_mobilenet_v3_large_320_fpn(
|
||||
weights=FasterRCNN_MobileNet_V3_Large_320_FPN_Weights.DEFAULT,
|
||||
box_score_thresh=0.7,
|
||||
rpn_post_nms_top_n_test=100,
|
||||
rpn_score_thresh=0.4,
|
||||
rpn_pre_nms_top_n_test=150,
|
||||
)
|
||||
|
||||
model.eval()
|
||||
script_model = torch.jit.script(model)
|
||||
opt_script_model = optimize_for_mobile(script_model)
|
||||
opt_script_model.save("app/src/main/assets/frcnn_mnetv3.pt")
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
import os
|
||||
import platform
|
||||
import statistics
|
||||
|
||||
import torch
|
||||
import torch.utils.benchmark as benchmark
|
||||
import torchvision
|
||||
|
||||
|
||||
def print_machine_specs():
|
||||
print("Processor:", platform.processor())
|
||||
print("Platform:", platform.platform())
|
||||
print("Logical CPUs:", os.cpu_count())
|
||||
print(f"\nCUDA device: {torch.cuda.get_device_name()}")
|
||||
print(f"Total Memory: {torch.cuda.get_device_properties(0).total_memory / 1e9:.2f} GB")
|
||||
|
||||
|
||||
def get_data():
|
||||
transform = torchvision.transforms.Compose(
|
||||
[
|
||||
torchvision.transforms.PILToTensor(),
|
||||
]
|
||||
)
|
||||
path = os.path.join(os.getcwd(), "data")
|
||||
testset = torchvision.datasets.Places365(
|
||||
root="./data", download=not os.path.exists(path), transform=transform, split="val"
|
||||
)
|
||||
testloader = torch.utils.data.DataLoader(
|
||||
testset, batch_size=1000, shuffle=False, num_workers=1, collate_fn=lambda batch: [r[0] for r in batch]
|
||||
)
|
||||
return next(iter(testloader))
|
||||
|
||||
|
||||
def run_encoding_benchmark(decoded_images):
|
||||
results = []
|
||||
for device in ["cpu", "cuda"]:
|
||||
decoded_images_device = [t.to(device=device) for t in decoded_images]
|
||||
for size in [1, 100, 1000]:
|
||||
for num_threads in [1, 12, 24]:
|
||||
for stmt, strat in zip(
|
||||
[
|
||||
"[torchvision.io.encode_jpeg(img) for img in decoded_images_device_trunc]",
|
||||
"torchvision.io.encode_jpeg(decoded_images_device_trunc)",
|
||||
],
|
||||
["unfused", "fused"],
|
||||
):
|
||||
decoded_images_device_trunc = decoded_images_device[:size]
|
||||
t = benchmark.Timer(
|
||||
stmt=stmt,
|
||||
setup="import torchvision",
|
||||
globals={"decoded_images_device_trunc": decoded_images_device_trunc},
|
||||
label="Image Encoding",
|
||||
sub_label=f"{device.upper()} ({strat}): {stmt}",
|
||||
description=f"{size} images",
|
||||
num_threads=num_threads,
|
||||
)
|
||||
results.append(t.blocked_autorange())
|
||||
compare = benchmark.Compare(results)
|
||||
compare.print()
|
||||
|
||||
|
||||
def run_decoding_benchmark(encoded_images):
|
||||
results = []
|
||||
for device in ["cpu", "cuda"]:
|
||||
for size in [1, 100, 1000]:
|
||||
for num_threads in [1, 12, 24]:
|
||||
for stmt, strat in zip(
|
||||
[
|
||||
f"[torchvision.io.decode_jpeg(img, device='{device}') for img in encoded_images_trunc]",
|
||||
f"torchvision.io.decode_jpeg(encoded_images_trunc, device='{device}')",
|
||||
],
|
||||
["unfused", "fused"],
|
||||
):
|
||||
encoded_images_trunc = encoded_images[:size]
|
||||
t = benchmark.Timer(
|
||||
stmt=stmt,
|
||||
setup="import torchvision",
|
||||
globals={"encoded_images_trunc": encoded_images_trunc},
|
||||
label="Image Decoding",
|
||||
sub_label=f"{device.upper()} ({strat}): {stmt}",
|
||||
description=f"{size} images",
|
||||
num_threads=num_threads,
|
||||
)
|
||||
results.append(t.blocked_autorange())
|
||||
compare = benchmark.Compare(results)
|
||||
compare.print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print_machine_specs()
|
||||
decoded_images = get_data()
|
||||
mean_h, mean_w = statistics.mean(t.shape[-2] for t in decoded_images), statistics.mean(
|
||||
t.shape[-1] for t in decoded_images
|
||||
)
|
||||
print(f"\nMean image size: {int(mean_h)}x{int(mean_w)}")
|
||||
run_encoding_benchmark(decoded_images)
|
||||
encoded_images_cuda = torchvision.io.encode_jpeg([img.cuda() for img in decoded_images])
|
||||
encoded_images_cpu = [img.cpu() for img in encoded_images_cuda]
|
||||
run_decoding_benchmark(encoded_images_cpu)
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
# TorchVisionConfig.cmake
|
||||
# --------------------
|
||||
#
|
||||
# Exported targets:: Vision
|
||||
#
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set(PN TorchVision)
|
||||
|
||||
# location of include/torchvision
|
||||
set(${PN}_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@")
|
||||
|
||||
set(${PN}_LIBRARY "")
|
||||
set(${PN}_DEFINITIONS USING_${PN})
|
||||
|
||||
check_required_components(${PN})
|
||||
|
||||
|
||||
if(NOT (CMAKE_VERSION VERSION_LESS 3.0))
|
||||
#-----------------------------------------------------------------------------
|
||||
# Don't include targets if this file is being picked up by another
|
||||
# project which has already built this as a subproject
|
||||
#-----------------------------------------------------------------------------
|
||||
if(NOT TARGET ${PN}::${PN})
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/${PN}Targets.cmake")
|
||||
|
||||
target_include_directories(${PN}::${PN} INTERFACE "${${PN}_INCLUDE_DIR}")
|
||||
|
||||
if(@WITH_CUDA@)
|
||||
target_compile_definitions(${PN}::${PN} INTERFACE WITH_CUDA)
|
||||
endif()
|
||||
|
||||
find_package(Torch REQUIRED)
|
||||
target_link_libraries(${PN}::${PN} INTERFACE torch)
|
||||
|
||||
if(@WITH_PNG@)
|
||||
find_package(PNG REQUIRED)
|
||||
target_link_libraries(${PN}::${PN} INTERFACE ${PNG_LIBRARY})
|
||||
target_compile_definitions(${PN}::${PN} INTERFACE PNG_FOUND)
|
||||
endif()
|
||||
|
||||
if(@WITH_JPEG@)
|
||||
find_package(JPEG REQUIRED)
|
||||
target_link_libraries(${PN}::${PN} INTERFACE ${JPEG_LIBRARIES})
|
||||
target_compile_definitions(${PN}::${PN} INTERFACE JPEG_FOUND)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake
|
||||
# files which are included with CMake 2.8.4
|
||||
# It has been altered for iOS development
|
||||
|
||||
# Options:
|
||||
#
|
||||
# IOS_PLATFORM = OS (default) or SIMULATOR
|
||||
# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders
|
||||
# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch.
|
||||
# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch.
|
||||
#
|
||||
# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder
|
||||
# By default this location is automatically chosen based on the IOS_PLATFORM value above.
|
||||
# If set manually, it will override the default location and force the user of a particular Developer Platform
|
||||
#
|
||||
# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder
|
||||
# By default this location is automatically chosen based on the CMAKE_IOS_DEVELOPER_ROOT value.
|
||||
# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path.
|
||||
# If set manually, this will force the use of a specific SDK version
|
||||
|
||||
# Macros:
|
||||
#
|
||||
# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE)
|
||||
# A convenience macro for setting xcode specific properties on targets
|
||||
# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1")
|
||||
#
|
||||
# find_host_package (PROGRAM ARGS)
|
||||
# A macro used to find executable programs on the host system, not within the iOS environment.
|
||||
# Thanks to the android-cmake project for providing the command
|
||||
|
||||
# Standard settings
|
||||
set(CMAKE_SYSTEM_NAME Darwin)
|
||||
set(CMAKE_SYSTEM_VERSION 1)
|
||||
set(UNIX True)
|
||||
set(APPLE True)
|
||||
set(IOS True)
|
||||
|
||||
# Required as of cmake 2.8.10
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE)
|
||||
|
||||
# Determine the cmake host system version so we know where to find the iOS SDKs
|
||||
find_program(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin)
|
||||
if(CMAKE_UNAME)
|
||||
exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
|
||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")
|
||||
endif(CMAKE_UNAME)
|
||||
|
||||
# Force the compilers to gcc for iOS
|
||||
set(CMAKE_C_COMPILER /usr/bin/gcc CACHE STRING "")
|
||||
set(CMAKE_CXX_COMPILER /usr/bin/g++ CACHE STRING "")
|
||||
set(CMAKE_AR ar CACHE FILEPATH "" FORCE)
|
||||
set(CMAKE_RANLIB ranlib CACHE FILEPATH "" FORCE)
|
||||
set(PKG_CONFIG_EXECUTABLE pkg-config CACHE FILEPATH "" FORCE)
|
||||
|
||||
# Setup iOS platform unless specified manually with IOS_PLATFORM
|
||||
if(NOT DEFINED IOS_PLATFORM)
|
||||
set(IOS_PLATFORM "OS")
|
||||
endif(NOT DEFINED IOS_PLATFORM)
|
||||
set(IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform")
|
||||
|
||||
# Check the platform selection and setup for developer root
|
||||
if(${IOS_PLATFORM} STREQUAL "OS")
|
||||
set(IOS_PLATFORM_LOCATION "iPhoneOS.platform")
|
||||
set(XCODE_IOS_PLATFORM iphoneos)
|
||||
|
||||
# This causes the installers to properly locate the output libraries
|
||||
set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos")
|
||||
elseif(${IOS_PLATFORM} STREQUAL "SIMULATOR")
|
||||
set(IOS_PLATFORM_LOCATION "iPhoneSimulator.platform")
|
||||
set(XCODE_IOS_PLATFORM iphonesimulator)
|
||||
|
||||
# This causes the installers to properly locate the output libraries
|
||||
set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator")
|
||||
elseif(${IOS_PLATFORM} STREQUAL "WATCHOS")
|
||||
set(IOS_PLATFORM_LOCATION "WatchOS.platform")
|
||||
set(XCODE_IOS_PLATFORM watchos)
|
||||
|
||||
# This causes the installers to properly locate the output libraries
|
||||
set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-watchos")
|
||||
else(${IOS_PLATFORM} STREQUAL "OS")
|
||||
message(FATAL_ERROR
|
||||
"Unsupported IOS_PLATFORM value selected. "
|
||||
"Please choose OS, SIMULATOR, or WATCHOS.")
|
||||
endif()
|
||||
|
||||
# All iOS/Darwin specific settings - some may be redundant
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "lib")
|
||||
set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib")
|
||||
set(CMAKE_SHARED_MODULE_PREFIX "lib")
|
||||
set(CMAKE_SHARED_MODULE_SUFFIX ".so")
|
||||
set(CMAKE_MODULE_EXISTS 1)
|
||||
set(CMAKE_DL_LIBS "")
|
||||
|
||||
set(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ")
|
||||
set(CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ")
|
||||
set(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}")
|
||||
set(CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}")
|
||||
|
||||
if(IOS_DEPLOYMENT_TARGET)
|
||||
set(XCODE_IOS_PLATFORM_VERSION_FLAGS "-m${XCODE_IOS_PLATFORM}-version-min=${IOS_DEPLOYMENT_TARGET}")
|
||||
endif()
|
||||
|
||||
# Hidden visibility is required for cxx on iOS
|
||||
set(CMAKE_C_FLAGS_INIT "${XCODE_IOS_PLATFORM_VERSION_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_INIT "${XCODE_IOS_PLATFORM_VERSION_FLAGS} -fvisibility-inlines-hidden")
|
||||
|
||||
set(CMAKE_C_LINK_FLAGS "${XCODE_IOS_PLATFORM_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}")
|
||||
set(CMAKE_CXX_LINK_FLAGS "${XCODE_IOS_PLATFORM_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}")
|
||||
|
||||
set(CMAKE_PLATFORM_HAS_INSTALLNAME 1)
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names")
|
||||
set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names")
|
||||
set(CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,")
|
||||
set(CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,")
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a")
|
||||
|
||||
# hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree
|
||||
# (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache
|
||||
# and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun)
|
||||
# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex
|
||||
if(NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
|
||||
find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool)
|
||||
endif(NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
|
||||
|
||||
# Setup iOS deployment target
|
||||
set(IOS_DEPLOYMENT_TARGET ${IOS_DEPLOYMENT_TARGET} CACHE STRING "Minimum iOS version")
|
||||
|
||||
# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT
|
||||
# Note Xcode 4.3 changed the installation location, choose the most recent one available
|
||||
exec_program(/usr/bin/xcode-select ARGS -print-path OUTPUT_VARIABLE CMAKE_XCODE_DEVELOPER_DIR)
|
||||
set(XCODE_POST_43_ROOT "${CMAKE_XCODE_DEVELOPER_DIR}/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
|
||||
set(XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
|
||||
if(NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
|
||||
if(EXISTS ${XCODE_POST_43_ROOT})
|
||||
set(CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT})
|
||||
elseif(EXISTS ${XCODE_PRE_43_ROOT})
|
||||
set(CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT})
|
||||
endif(EXISTS ${XCODE_POST_43_ROOT})
|
||||
endif(NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
|
||||
set(CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform")
|
||||
|
||||
# Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT
|
||||
if(NOT DEFINED CMAKE_IOS_SDK_ROOT)
|
||||
file(GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*")
|
||||
if(_CMAKE_IOS_SDKS)
|
||||
list(SORT _CMAKE_IOS_SDKS)
|
||||
list(REVERSE _CMAKE_IOS_SDKS)
|
||||
list(GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT)
|
||||
else(_CMAKE_IOS_SDKS)
|
||||
message(FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.")
|
||||
endif(_CMAKE_IOS_SDKS)
|
||||
message(STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}")
|
||||
endif(NOT DEFINED CMAKE_IOS_SDK_ROOT)
|
||||
set(CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK")
|
||||
|
||||
# Set the sysroot default to the most recent SDK
|
||||
set(CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support")
|
||||
|
||||
# set the architecture for iOS
|
||||
if(IOS_PLATFORM STREQUAL "OS")
|
||||
set(DEFAULT_IOS_ARCH "arm64")
|
||||
elseif(IOS_PLATFORM STREQUAL "SIMULATOR")
|
||||
set(DEFAULT_IOS_ARCH "x86_64")
|
||||
elseif(IOS_PLATFORM STREQUAL "WATCHOS")
|
||||
set(DEFAULT_IOS_ARCH "armv7k;arm64_32")
|
||||
endif()
|
||||
|
||||
set(IOS_ARCH ${DEFAULT_IOS_ARCH} CACHE STRING "Build architecture for iOS")
|
||||
set(CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE STRING "Build architecture for iOS")
|
||||
|
||||
# Set the find root to the iOS developer roots and to user defined paths
|
||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE STRING "iOS find search path root")
|
||||
|
||||
# default to searching for frameworks first
|
||||
set(CMAKE_FIND_FRAMEWORK FIRST)
|
||||
|
||||
# set up the default search directories for frameworks
|
||||
set(CMAKE_SYSTEM_FRAMEWORK_PATH
|
||||
${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks
|
||||
${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks
|
||||
${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks
|
||||
)
|
||||
|
||||
# only search the iOS sdks, not the remainder of the host filesystem
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
# This little macro lets you set any XCode specific property
|
||||
macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
|
||||
set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
|
||||
endmacro(set_xcode_property)
|
||||
|
||||
# This macro lets you find executable programs on the host system
|
||||
macro(find_host_package)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
|
||||
set(IOS FALSE)
|
||||
|
||||
find_package(${ARGN})
|
||||
|
||||
set(IOS TRUE)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
endmacro(find_host_package)
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
ifneq ($(EXAMPLES_PATTERN),)
|
||||
EXAMPLES_PATTERN_OPTS := -D sphinx_gallery_conf.filename_pattern="$(EXAMPLES_PATTERN)"
|
||||
endif
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS = -W -j auto $(EXAMPLES_PATTERN_OPTS)
|
||||
SPHINXBUILD = sphinx-build
|
||||
SPHINXPROJ = torchvision
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
docset: html
|
||||
doc2dash --name $(SPHINXPROJ) --icon $(SOURCEDIR)/_static/img/pytorch-logo-flame.png --enable-js --online-redirect-url http://pytorch.org/vision/ --force $(BUILDDIR)/html/
|
||||
|
||||
# Manually fix because Zeal doesn't deal well with `icon.png`-only at 2x resolution.
|
||||
cp $(SPHINXPROJ).docset/icon.png $(SPHINXPROJ).docset/icon@2x.png
|
||||
convert $(SPHINXPROJ).docset/icon@2x.png -resize 16x16 $(SPHINXPROJ).docset/icon.png
|
||||
|
||||
html-noplot: # Avoids running the gallery examples, which may take time
|
||||
$(SPHINXBUILD) -D plot_gallery=0 -b html "${SOURCEDIR}" "$(BUILDDIR)"/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
rm -rf $(SOURCEDIR)/auto_examples/ # sphinx-gallery
|
||||
rm -rf $(SOURCEDIR)/gen_modules/ # sphinx-gallery
|
||||
rm -rf $(SOURCEDIR)/generated/ # autosummary
|
||||
rm -rf $(SOURCEDIR)/models/generated # autosummary
|
||||
|
||||
.PHONY: help Makefile docset
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
set SPHINXPROJ=torchvision
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
matplotlib
|
||||
numpy
|
||||
sphinx-copybutton>=0.3.1
|
||||
sphinx-gallery>=0.11.1
|
||||
sphinx==5.0.0
|
||||
tabulate
|
||||
-e git+https://github.com/pytorch/pytorch_sphinx_theme.git#egg=pytorch_sphinx_theme
|
||||
pycocotools
|
||||
35
cache/torch/hub/pytorch_vision_main/docs/source/_static/css/custom_torchvision.css
vendored
Normal file
35
cache/torch/hub/pytorch_vision_main/docs/source/_static/css/custom_torchvision.css
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/* This rule should be removed once
|
||||
https://github.com/pytorch/pytorch_sphinx_theme/issues/125 is fixed.
|
||||
|
||||
We override the rule so that the links to the notebooks aren't hidden in the
|
||||
gallery examples. pytorch_sphinx_theme is supposed to customize those links so
|
||||
that they render nicely (look at the nice links on top of the tutorials
|
||||
examples) but it doesn't work for repos that are not the tutorial repo, and in
|
||||
torchvision it just hides the links. So we have to put them back here */
|
||||
article.pytorch-article .sphx-glr-download-link-note.admonition.note,
|
||||
article.pytorch-article .reference.download.internal, article.pytorch-article .sphx-glr-signature {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* These 2 rules below are for the weight tables (generated in conf.py) to look
|
||||
* better. In particular we make their row height shorter */
|
||||
.table-weights td, .table-weights th {
|
||||
margin-bottom: 0.2rem;
|
||||
padding: 0 !important;
|
||||
line-height: 1 !important;
|
||||
}
|
||||
.table-weights p {
|
||||
margin-bottom: 0.2rem !important;
|
||||
}
|
||||
|
||||
/* Fix for Sphinx gallery 0.11
|
||||
See https://github.com/sphinx-gallery/sphinx-gallery/issues/990
|
||||
*/
|
||||
article.pytorch-article .sphx-glr-thumbnails .sphx-glr-thumbcontainer {
|
||||
width: unset;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
article.pytorch-article div.section div.wy-table-responsive tbody td {
|
||||
width: 50%;
|
||||
}
|
||||
BIN
cache/torch/hub/pytorch_vision_main/docs/source/_static/img/pytorch-logo-dark.png
vendored
Normal file
BIN
cache/torch/hub/pytorch_vision_main/docs/source/_static/img/pytorch-logo-dark.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
24
cache/torch/hub/pytorch_vision_main/docs/source/_static/img/pytorch-logo-dark.svg
vendored
Normal file
24
cache/torch/hub/pytorch_vision_main/docs/source/_static/img/pytorch-logo-dark.svg
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 199.7 40.2" style="enable-background:new 0 0 199.7 40.2;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F05732;}
|
||||
.st1{fill:#9E529F;}
|
||||
.st2{fill:#333333;}
|
||||
</style>
|
||||
<path class="st0" d="M102.7,12.2c-1.3-1-1.8,3.9-4.4,3.9c-3,0-4-13-6.3-13c-0.7,0-0.8-0.4-7.9,21.3c-2.9,9,4.4,15.8,11.8,15.8
|
||||
c4.6,0,12.3-3,12.3-12.6C108.2,20.5,104.7,13.7,102.7,12.2z M95.8,35.3c-3.7,0-6.7-3.1-6.7-7c0-3.9,3-7,6.7-7s6.7,3.1,6.7,7
|
||||
C102.5,32.1,99.5,35.3,95.8,35.3z"/>
|
||||
<path class="st1" d="M99.8,0c-0.5,0-1.8,2.5-1.8,3.6c0,1.5,1,2,1.8,2c0.8,0,1.8-0.5,1.8-2C101.5,2.5,100.2,0,99.8,0z"/>
|
||||
<path class="st2" d="M0,39.5V14.9h11.5c5.3,0,8.3,3.6,8.3,7.9c0,4.3-3,7.9-8.3,7.9H5.2v8.8H0z M14.4,22.8c0-2.1-1.6-3.3-3.7-3.3H5.2
|
||||
v6.6h5.5C12.8,26.1,14.4,24.8,14.4,22.8z"/>
|
||||
<path class="st2" d="M35.2,39.5V29.4l-9.4-14.5h6l6.1,9.8l6.1-9.8h5.9l-9.4,14.5v10.1H35.2z"/>
|
||||
<path class="st2" d="M63.3,39.5v-20h-7.2v-4.6h19.6v4.6h-7.2v20H63.3z"/>
|
||||
<path class="st2" d="M131.4,39.5l-4.8-8.7h-3.8v8.7h-5.2V14.9H129c5.1,0,8.3,3.4,8.3,7.9c0,4.3-2.8,6.7-5.4,7.3l5.6,9.4H131.4z
|
||||
M131.9,22.8c0-2-1.6-3.3-3.7-3.3h-5.5v6.6h5.5C130.3,26.1,131.9,24.9,131.9,22.8z"/>
|
||||
<path class="st2" d="M145.6,27.2c0-7.6,5.7-12.7,13.1-12.7c5.4,0,8.5,2.9,10.3,6l-4.5,2.2c-1-2-3.2-3.6-5.8-3.6
|
||||
c-4.5,0-7.7,3.4-7.7,8.1c0,4.6,3.2,8.1,7.7,8.1c2.5,0,4.7-1.6,5.8-3.6l4.5,2.2c-1.7,3.1-4.9,6-10.3,6
|
||||
C151.3,39.9,145.6,34.7,145.6,27.2z"/>
|
||||
<path class="st2" d="M194.5,39.5V29.1h-11.6v10.4h-5.2V14.9h5.2v9.7h11.6v-9.7h5.3v24.6H194.5z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
BIN
cache/torch/hub/pytorch_vision_main/docs/source/_static/img/pytorch-logo-flame.png
vendored
Normal file
BIN
cache/torch/hub/pytorch_vision_main/docs/source/_static/img/pytorch-logo-flame.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1010 B |
33
cache/torch/hub/pytorch_vision_main/docs/source/_static/img/pytorch-logo-flame.svg
vendored
Normal file
33
cache/torch/hub/pytorch_vision_main/docs/source/_static/img/pytorch-logo-flame.svg
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
height="40.200001"
|
||||
width="40.200001"
|
||||
xml:space="preserve"
|
||||
viewBox="0 0 40.200002 40.2"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Layer_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata4717"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs4715" /><style
|
||||
id="style4694"
|
||||
type="text/css">
|
||||
.st0{fill:#F05732;}
|
||||
.st1{fill:#9E529F;}
|
||||
.st2{fill:#333333;}
|
||||
</style><path
|
||||
style="fill:#f05732"
|
||||
id="path4696"
|
||||
d="m 26.975479,12.199999 c -1.3,-1 -1.8,3.9 -4.4,3.9 -3,0 -4,-12.9999998 -6.3,-12.9999998 -0.7,0 -0.8,-0.4 -7.9000003,21.2999998 -2.9000001,9 4.4000003,15.8 11.8000003,15.8 4.6,0 12.3,-3 12.3,-12.6 0,-7.1 -3.5,-13.9 -5.5,-15.4 z m -6.9,23.1 c -3.7,0 -6.7,-3.1 -6.7,-7 0,-3.9 3,-7 6.7,-7 3.7,0 6.7,3.1 6.7,7 0,3.8 -3,7 -6.7,7 z"
|
||||
class="st0" /><path
|
||||
style="fill:#9e529f"
|
||||
id="path4698"
|
||||
d="m 24.075479,-7.6293945e-7 c -0.5,0 -1.8,2.49999996293945 -1.8,3.59999996293945 0,1.5 1,2 1.8,2 0.8,0 1.8,-0.5 1.8,-2 -0.1,-1.1 -1.4,-3.59999996293945 -1.8,-3.59999996293945 z"
|
||||
class="st1" /></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,9 @@
|
|||
.. role:: hidden
|
||||
:class: hidden-section
|
||||
.. currentmodule:: {{ module }}
|
||||
|
||||
|
||||
{{ name | underline}}
|
||||
|
||||
.. autoclass:: {{ name }}
|
||||
:members:
|
||||
12
cache/torch/hub/pytorch_vision_main/docs/source/_templates/class_dataset.rst
vendored
Normal file
12
cache/torch/hub/pytorch_vision_main/docs/source/_templates/class_dataset.rst
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
.. role:: hidden
|
||||
:class: hidden-section
|
||||
.. currentmodule:: {{ module }}
|
||||
|
||||
|
||||
{{ name | underline}}
|
||||
|
||||
.. autoclass:: {{ name }}
|
||||
:members:
|
||||
__getitem__,
|
||||
{% if "category_name" in methods %} category_name {% endif %}
|
||||
:special-members:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
.. role:: hidden
|
||||
:class: hidden-section
|
||||
.. currentmodule:: {{ module }}
|
||||
|
||||
|
||||
{{ name | underline}}
|
||||
|
||||
.. autofunction:: {{ name }}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{% extends "!layout.html" %}
|
||||
|
||||
{% block sidebartitle %}
|
||||
<div class="version">
|
||||
<a href='https://pytorch.org/vision/versions.html'>{{ version }} ▼</a>
|
||||
</div>
|
||||
{% include "searchbox.html" %}
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
from docutils import nodes
|
||||
from docutils.parsers.rst import Directive
|
||||
|
||||
|
||||
class BetaStatus(Directive):
|
||||
has_content = True
|
||||
text = "The {api_name} is in Beta stage, and backward compatibility is not guaranteed."
|
||||
node = nodes.warning
|
||||
|
||||
def run(self):
|
||||
text = self.text.format(api_name=" ".join(self.content))
|
||||
return [self.node("", nodes.paragraph("", "", nodes.Text(text)))]
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_directive("betastatus", BetaStatus)
|
||||
return {
|
||||
"version": "0.1",
|
||||
"parallel_read_safe": True,
|
||||
"parallel_write_safe": True,
|
||||
}
|
||||
|
|
@ -0,0 +1,524 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# PyTorch documentation build configuration file, created by
|
||||
# sphinx-quickstart on Fri Dec 23 13:31:47 2016.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
import os
|
||||
import sys
|
||||
import textwrap
|
||||
from copy import copy
|
||||
from pathlib import Path
|
||||
|
||||
import pytorch_sphinx_theme
|
||||
import torchvision
|
||||
import torchvision.models as M
|
||||
from sphinx_gallery.sorting import ExplicitOrder
|
||||
from tabulate import tabulate
|
||||
|
||||
sys.path.append(os.path.abspath("."))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# Required version of sphinx is set from docs/requirements.txt
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.autosummary",
|
||||
"sphinx.ext.doctest",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.todo",
|
||||
"sphinx.ext.mathjax",
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx.ext.viewcode",
|
||||
"sphinx.ext.duration",
|
||||
"sphinx_gallery.gen_gallery",
|
||||
"sphinx_copybutton",
|
||||
"beta_status",
|
||||
]
|
||||
|
||||
# We override sphinx-gallery's example header to prevent sphinx-gallery from
|
||||
# creating a note at the top of the renderred notebook.
|
||||
# https://github.com/sphinx-gallery/sphinx-gallery/blob/451ccba1007cc523f39cbcc960ebc21ca39f7b75/sphinx_gallery/gen_rst.py#L1267-L1271
|
||||
# This is because we also want to add a link to google Colab, so we write our own note in each example.
|
||||
from sphinx_gallery import gen_rst
|
||||
|
||||
gen_rst.EXAMPLE_HEADER = """
|
||||
.. DO NOT EDIT.
|
||||
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
|
||||
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
|
||||
.. "{0}"
|
||||
.. LINE NUMBERS ARE GIVEN BELOW.
|
||||
|
||||
.. rst-class:: sphx-glr-example-title
|
||||
|
||||
.. _sphx_glr_{1}:
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class CustomGalleryExampleSortKey:
|
||||
# See https://sphinx-gallery.github.io/stable/configuration.html#sorting-gallery-examples
|
||||
# and https://github.com/sphinx-gallery/sphinx-gallery/blob/master/sphinx_gallery/sorting.py
|
||||
def __init__(self, src_dir):
|
||||
self.src_dir = src_dir
|
||||
|
||||
transforms_subsection_order = [
|
||||
"plot_transforms_getting_started.py",
|
||||
"plot_transforms_illustrations.py",
|
||||
"plot_transforms_e2e.py",
|
||||
"plot_cutmix_mixup.py",
|
||||
"plot_custom_transforms.py",
|
||||
"plot_tv_tensors.py",
|
||||
"plot_custom_tv_tensors.py",
|
||||
]
|
||||
|
||||
def __call__(self, filename):
|
||||
if "gallery/transforms" in self.src_dir:
|
||||
try:
|
||||
return self.transforms_subsection_order.index(filename)
|
||||
except ValueError as e:
|
||||
raise ValueError(
|
||||
"Looks like you added an example in gallery/transforms? "
|
||||
"You need to specify its order in docs/source/conf.py. Look for CustomGalleryExampleSortKey."
|
||||
) from e
|
||||
else:
|
||||
# For other subsections we just sort alphabetically by filename
|
||||
return filename
|
||||
|
||||
|
||||
sphinx_gallery_conf = {
|
||||
"examples_dirs": "../../gallery/", # path to your example scripts
|
||||
"gallery_dirs": "auto_examples", # path to where to save gallery generated output
|
||||
"subsection_order": ExplicitOrder(["../../gallery/transforms", "../../gallery/others"]),
|
||||
"backreferences_dir": "gen_modules/backreferences",
|
||||
"doc_module": ("torchvision",),
|
||||
"remove_config_comments": True,
|
||||
"ignore_pattern": "helpers.py",
|
||||
"within_subsection_order": CustomGalleryExampleSortKey,
|
||||
}
|
||||
|
||||
napoleon_use_ivar = True
|
||||
napoleon_numpy_docstring = False
|
||||
napoleon_google_docstring = True
|
||||
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
source_suffix = {
|
||||
".rst": "restructuredtext",
|
||||
}
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = "Torchvision"
|
||||
copyright = "2017-present, Torch Contributors"
|
||||
author = "Torch Contributors"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
# version: The short X.Y version.
|
||||
# release: The full version, including alpha/beta/rc tags.
|
||||
if os.environ.get("TORCHVISION_SANITIZE_VERSION_STR_IN_DOCS", None):
|
||||
# Turn 1.11.0aHASH into 1.11 (major.minor only)
|
||||
version = release = ".".join(torchvision.__version__.split(".")[:2])
|
||||
html_title = " ".join((project, version, "documentation"))
|
||||
else:
|
||||
version = f"main ({torchvision.__version__})"
|
||||
release = "main"
|
||||
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = "en"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = []
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = True
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = "pytorch_sphinx_theme"
|
||||
html_theme_path = [pytorch_sphinx_theme.get_html_theme_path()]
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
html_theme_options = {
|
||||
"collapse_navigation": False,
|
||||
"display_version": True,
|
||||
"logo_only": True,
|
||||
"pytorch_project": "docs",
|
||||
"navigation_with_keys": True,
|
||||
"analytics_id": "GTM-T8XT4PS",
|
||||
}
|
||||
|
||||
html_logo = "_static/img/pytorch-logo-dark.svg"
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ["_static"]
|
||||
|
||||
# TODO: remove this once https://github.com/pytorch/pytorch_sphinx_theme/issues/125 is fixed
|
||||
html_css_files = [
|
||||
"css/custom_torchvision.css",
|
||||
]
|
||||
|
||||
# -- Options for HTMLHelp output ------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = "PyTorchdoc"
|
||||
|
||||
|
||||
autosummary_generate = True
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, "pytorch.tex", "torchvision Documentation", "Torch Contributors", "manual"),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [(master_doc, "torchvision", "torchvision Documentation", [author], 1)]
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(
|
||||
master_doc,
|
||||
"torchvision",
|
||||
"torchvision Documentation",
|
||||
author,
|
||||
"torchvision",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {
|
||||
"python": ("https://docs.python.org/3/", None),
|
||||
"torch": ("https://pytorch.org/docs/stable/", None),
|
||||
"numpy": ("https://numpy.org/doc/stable/", None),
|
||||
"PIL": ("https://pillow.readthedocs.io/en/stable/", None),
|
||||
"matplotlib": ("https://matplotlib.org/stable/", None),
|
||||
}
|
||||
|
||||
# -- A patch that prevents Sphinx from cross-referencing ivar tags -------
|
||||
# See http://stackoverflow.com/a/41184353/3343043
|
||||
|
||||
from docutils import nodes
|
||||
from sphinx import addnodes
|
||||
from sphinx.util.docfields import TypedField
|
||||
|
||||
|
||||
def patched_make_field(self, types, domain, items, **kw):
|
||||
# `kw` catches `env=None` needed for newer sphinx while maintaining
|
||||
# backwards compatibility when passed along further down!
|
||||
|
||||
# type: (list, unicode, tuple) -> nodes.field # noqa: F821
|
||||
def handle_item(fieldarg, content):
|
||||
par = nodes.paragraph()
|
||||
par += addnodes.literal_strong("", fieldarg) # Patch: this line added
|
||||
# par.extend(self.make_xrefs(self.rolename, domain, fieldarg,
|
||||
# addnodes.literal_strong))
|
||||
if fieldarg in types:
|
||||
par += nodes.Text(" (")
|
||||
# NOTE: using .pop() here to prevent a single type node to be
|
||||
# inserted twice into the doctree, which leads to
|
||||
# inconsistencies later when references are resolved
|
||||
fieldtype = types.pop(fieldarg)
|
||||
if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text):
|
||||
typename = "".join(n.astext() for n in fieldtype)
|
||||
typename = typename.replace("int", "python:int")
|
||||
typename = typename.replace("long", "python:long")
|
||||
typename = typename.replace("float", "python:float")
|
||||
typename = typename.replace("type", "python:type")
|
||||
par.extend(self.make_xrefs(self.typerolename, domain, typename, addnodes.literal_emphasis, **kw))
|
||||
else:
|
||||
par += fieldtype
|
||||
par += nodes.Text(")")
|
||||
par += nodes.Text(" -- ")
|
||||
par += content
|
||||
return par
|
||||
|
||||
fieldname = nodes.field_name("", self.label)
|
||||
if len(items) == 1 and self.can_collapse:
|
||||
fieldarg, content = items[0]
|
||||
bodynode = handle_item(fieldarg, content)
|
||||
else:
|
||||
bodynode = self.list_type()
|
||||
for fieldarg, content in items:
|
||||
bodynode += nodes.list_item("", handle_item(fieldarg, content))
|
||||
fieldbody = nodes.field_body("", bodynode)
|
||||
return nodes.field("", fieldname, fieldbody)
|
||||
|
||||
|
||||
TypedField.make_field = patched_make_field
|
||||
|
||||
|
||||
def inject_minigalleries(app, what, name, obj, options, lines):
|
||||
"""Inject a minigallery into a docstring.
|
||||
|
||||
This avoids having to manually write the .. minigallery directive for every item we want a minigallery for,
|
||||
as it would be easy to miss some.
|
||||
|
||||
This callback is called after the .. auto directives (like ..autoclass) have been processed,
|
||||
and modifies the lines parameter inplace to add the .. minigallery that will show which examples
|
||||
are using which object.
|
||||
|
||||
It's a bit hacky, but not *that* hacky when you consider that the recommended way is to do pretty much the same,
|
||||
but instead with templates using autosummary (which we don't want to use):
|
||||
(https://sphinx-gallery.github.io/stable/configuration.html#auto-documenting-your-api-with-links-to-examples)
|
||||
|
||||
For docs on autodoc-process-docstring, see the autodoc docs:
|
||||
https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html
|
||||
"""
|
||||
|
||||
if what in ("class", "function"):
|
||||
lines.append(f".. minigallery:: {name}")
|
||||
lines.append(f" :add-heading: Examples using ``{name.split('.')[-1]}``:")
|
||||
# avoid heading entirely to avoid warning. As a bonud it actually renders better
|
||||
lines.append(" :heading-level: 9")
|
||||
lines.append("\n")
|
||||
|
||||
|
||||
def inject_weight_metadata(app, what, name, obj, options, lines):
|
||||
"""This hook is used to generate docs for the models weights.
|
||||
|
||||
Objects like ResNet18_Weights are enums with fields, where each field is a Weight object.
|
||||
Enums aren't easily documented in Python so the solution we're going for is to:
|
||||
|
||||
- add an autoclass directive in the model's builder docstring, e.g.
|
||||
|
||||
```
|
||||
.. autoclass:: torchvision.models.ResNet34_Weights
|
||||
:members:
|
||||
```
|
||||
|
||||
(see resnet.py for an example)
|
||||
- then this hook is called automatically when building the docs, and it generates the text that gets
|
||||
used within the autoclass directive.
|
||||
"""
|
||||
|
||||
if getattr(obj, "__name__", "").endswith(("_Weights", "_QuantizedWeights")):
|
||||
|
||||
if len(obj) == 0:
|
||||
lines[:] = ["There are no available pre-trained weights."]
|
||||
return
|
||||
|
||||
lines[:] = [
|
||||
"The model builder above accepts the following values as the ``weights`` parameter.",
|
||||
f"``{obj.__name__}.DEFAULT`` is equivalent to ``{obj.DEFAULT}``. You can also use strings, e.g. "
|
||||
f"``weights='DEFAULT'`` or ``weights='{str(list(obj)[0]).split('.')[1]}'``.",
|
||||
]
|
||||
|
||||
if obj.__doc__ is not None and obj.__doc__ != "An enumeration.":
|
||||
# We only show the custom enum doc if it was overridden. The default one from Python is "An enumeration"
|
||||
lines.append("")
|
||||
lines.append(obj.__doc__)
|
||||
|
||||
lines.append("")
|
||||
|
||||
for field in obj:
|
||||
meta = copy(field.meta)
|
||||
|
||||
lines += [f"**{str(field)}**:", ""]
|
||||
lines += [meta.pop("_docs")]
|
||||
|
||||
if field == obj.DEFAULT:
|
||||
lines += [f"Also available as ``{obj.__name__}.DEFAULT``."]
|
||||
lines += [""]
|
||||
|
||||
table = []
|
||||
metrics = meta.pop("_metrics")
|
||||
for dataset, dataset_metrics in metrics.items():
|
||||
for metric_name, metric_value in dataset_metrics.items():
|
||||
table.append((f"{metric_name} (on {dataset})", str(metric_value)))
|
||||
|
||||
for k, v in meta.items():
|
||||
if k in {"recipe", "license"}:
|
||||
v = f"`link <{v}>`__"
|
||||
elif k == "min_size":
|
||||
v = f"height={v[0]}, width={v[1]}"
|
||||
elif k in {"categories", "keypoint_names"} and isinstance(v, list):
|
||||
max_visible = 3
|
||||
v_sample = ", ".join(v[:max_visible])
|
||||
v = f"{v_sample}, ... ({len(v)-max_visible} omitted)" if len(v) > max_visible else v_sample
|
||||
elif k == "_ops":
|
||||
v = f"{v:.2f}"
|
||||
k = "GIPS" if obj.__name__.endswith("_QuantizedWeights") else "GFLOPS"
|
||||
elif k == "_file_size":
|
||||
k = "File size"
|
||||
v = f"{v:.1f} MB"
|
||||
|
||||
table.append((str(k), str(v)))
|
||||
table = tabulate(table, tablefmt="rst")
|
||||
lines += [".. rst-class:: table-weights"] # Custom CSS class, see custom_torchvision.css
|
||||
lines += [".. table::", ""]
|
||||
lines += textwrap.indent(table, " " * 4).split("\n")
|
||||
lines.append("")
|
||||
lines.append(
|
||||
f"The inference transforms are available at ``{str(field)}.transforms`` and "
|
||||
f"perform the following preprocessing operations: {field.transforms().describe()}"
|
||||
)
|
||||
lines.append("")
|
||||
|
||||
|
||||
def generate_weights_table(module, table_name, metrics, dataset, include_patterns=None, exclude_patterns=None):
|
||||
weights_endswith = "_QuantizedWeights" if module.__name__.split(".")[-1] == "quantization" else "_Weights"
|
||||
weight_enums = [getattr(module, name) for name in dir(module) if name.endswith(weights_endswith)]
|
||||
weights = [w for weight_enum in weight_enums for w in weight_enum]
|
||||
|
||||
if include_patterns is not None:
|
||||
weights = [w for w in weights if any(p in str(w) for p in include_patterns)]
|
||||
if exclude_patterns is not None:
|
||||
weights = [w for w in weights if all(p not in str(w) for p in exclude_patterns)]
|
||||
|
||||
ops_name = "GIPS" if "QuantizedWeights" in weights_endswith else "GFLOPS"
|
||||
|
||||
metrics_keys, metrics_names = zip(*metrics)
|
||||
column_names = ["Weight"] + list(metrics_names) + ["Params"] + [ops_name, "Recipe"] # Final column order
|
||||
column_names = [f"**{name}**" for name in column_names] # Add bold
|
||||
|
||||
content = []
|
||||
for w in weights:
|
||||
row = [
|
||||
f":class:`{w} <{type(w).__name__}>`",
|
||||
*(w.meta["_metrics"][dataset][metric] for metric in metrics_keys),
|
||||
f"{w.meta['num_params']/1e6:.1f}M",
|
||||
f"{w.meta['_ops']:.2f}",
|
||||
f"`link <{w.meta['recipe']}>`__",
|
||||
]
|
||||
|
||||
content.append(row)
|
||||
|
||||
column_widths = ["110"] + ["18"] * len(metrics_names) + ["18"] * 2 + ["10"]
|
||||
widths_table = " ".join(column_widths)
|
||||
|
||||
table = tabulate(content, headers=column_names, tablefmt="rst")
|
||||
|
||||
generated_dir = Path("generated")
|
||||
generated_dir.mkdir(exist_ok=True)
|
||||
with open(generated_dir / f"{table_name}_table.rst", "w+") as table_file:
|
||||
table_file.write(".. rst-class:: table-weights\n") # Custom CSS class, see custom_torchvision.css
|
||||
table_file.write(".. table::\n")
|
||||
table_file.write(f" :widths: {widths_table} \n\n")
|
||||
table_file.write(f"{textwrap.indent(table, ' ' * 4)}\n\n")
|
||||
|
||||
|
||||
generate_weights_table(
|
||||
module=M, table_name="classification", metrics=[("acc@1", "Acc@1"), ("acc@5", "Acc@5")], dataset="ImageNet-1K"
|
||||
)
|
||||
generate_weights_table(
|
||||
module=M.quantization,
|
||||
table_name="classification_quant",
|
||||
metrics=[("acc@1", "Acc@1"), ("acc@5", "Acc@5")],
|
||||
dataset="ImageNet-1K",
|
||||
)
|
||||
generate_weights_table(
|
||||
module=M.detection,
|
||||
table_name="detection",
|
||||
metrics=[("box_map", "Box MAP")],
|
||||
exclude_patterns=["Mask", "Keypoint"],
|
||||
dataset="COCO-val2017",
|
||||
)
|
||||
generate_weights_table(
|
||||
module=M.detection,
|
||||
table_name="instance_segmentation",
|
||||
metrics=[("box_map", "Box MAP"), ("mask_map", "Mask MAP")],
|
||||
dataset="COCO-val2017",
|
||||
include_patterns=["Mask"],
|
||||
)
|
||||
generate_weights_table(
|
||||
module=M.detection,
|
||||
table_name="detection_keypoint",
|
||||
metrics=[("box_map", "Box MAP"), ("kp_map", "Keypoint MAP")],
|
||||
dataset="COCO-val2017",
|
||||
include_patterns=["Keypoint"],
|
||||
)
|
||||
generate_weights_table(
|
||||
module=M.segmentation,
|
||||
table_name="segmentation",
|
||||
metrics=[("miou", "Mean IoU"), ("pixel_acc", "pixelwise Acc")],
|
||||
dataset="COCO-val2017-VOC-labels",
|
||||
)
|
||||
generate_weights_table(
|
||||
module=M.video, table_name="video", metrics=[("acc@1", "Acc@1"), ("acc@5", "Acc@5")], dataset="Kinetics-400"
|
||||
)
|
||||
|
||||
|
||||
def setup(app):
|
||||
|
||||
app.connect("autodoc-process-docstring", inject_minigalleries)
|
||||
app.connect("autodoc-process-docstring", inject_weight_metadata)
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
.. _datasets:
|
||||
|
||||
Datasets
|
||||
========
|
||||
|
||||
Torchvision provides many built-in datasets in the ``torchvision.datasets``
|
||||
module, as well as utility classes for building your own datasets.
|
||||
|
||||
Built-in datasets
|
||||
-----------------
|
||||
|
||||
All datasets are subclasses of :class:`torch.utils.data.Dataset`
|
||||
i.e, they have ``__getitem__`` and ``__len__`` methods implemented.
|
||||
Hence, they can all be passed to a :class:`torch.utils.data.DataLoader`
|
||||
which can load multiple samples in parallel using ``torch.multiprocessing`` workers.
|
||||
For example: ::
|
||||
|
||||
imagenet_data = torchvision.datasets.ImageNet('path/to/imagenet_root/')
|
||||
data_loader = torch.utils.data.DataLoader(imagenet_data,
|
||||
batch_size=4,
|
||||
shuffle=True,
|
||||
num_workers=args.nThreads)
|
||||
|
||||
.. currentmodule:: torchvision.datasets
|
||||
|
||||
All the datasets have almost similar API. They all have two common arguments:
|
||||
``transform`` and ``target_transform`` to transform the input and target respectively.
|
||||
You can also create your own datasets using the provided :ref:`base classes <base_classes_datasets>`.
|
||||
|
||||
.. warning::
|
||||
|
||||
When a dataset object is created with ``download=True``, the files are first
|
||||
downloaded and extracted in the root directory. This download logic is not
|
||||
multi-process safe, so it may lead to conflicts / race conditions if it is
|
||||
run within a distributed setting. In distributed mode, we recommend creating
|
||||
a dummy dataset object to trigger the download logic *before* setting up
|
||||
distributed mode.
|
||||
|
||||
Image classification
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class_dataset.rst
|
||||
|
||||
Caltech101
|
||||
Caltech256
|
||||
CelebA
|
||||
CIFAR10
|
||||
CIFAR100
|
||||
Country211
|
||||
DTD
|
||||
EMNIST
|
||||
EuroSAT
|
||||
FakeData
|
||||
FashionMNIST
|
||||
FER2013
|
||||
FGVCAircraft
|
||||
Flickr8k
|
||||
Flickr30k
|
||||
Flowers102
|
||||
Food101
|
||||
GTSRB
|
||||
INaturalist
|
||||
ImageNet
|
||||
Imagenette
|
||||
KMNIST
|
||||
LFWPeople
|
||||
LSUN
|
||||
MNIST
|
||||
Omniglot
|
||||
OxfordIIITPet
|
||||
Places365
|
||||
PCAM
|
||||
QMNIST
|
||||
RenderedSST2
|
||||
SEMEION
|
||||
SBU
|
||||
StanfordCars
|
||||
STL10
|
||||
SUN397
|
||||
SVHN
|
||||
USPS
|
||||
|
||||
Image detection or segmentation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class_dataset.rst
|
||||
|
||||
CocoDetection
|
||||
CelebA
|
||||
Cityscapes
|
||||
Kitti
|
||||
OxfordIIITPet
|
||||
SBDataset
|
||||
VOCSegmentation
|
||||
VOCDetection
|
||||
WIDERFace
|
||||
|
||||
Optical Flow
|
||||
~~~~~~~~~~~~
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class_dataset.rst
|
||||
|
||||
FlyingChairs
|
||||
FlyingThings3D
|
||||
HD1K
|
||||
KittiFlow
|
||||
Sintel
|
||||
|
||||
Stereo Matching
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class_dataset.rst
|
||||
|
||||
CarlaStereo
|
||||
Kitti2012Stereo
|
||||
Kitti2015Stereo
|
||||
CREStereo
|
||||
FallingThingsStereo
|
||||
SceneFlowStereo
|
||||
SintelStereo
|
||||
InStereo2k
|
||||
ETH3DStereo
|
||||
Middlebury2014Stereo
|
||||
|
||||
Image pairs
|
||||
~~~~~~~~~~~
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class_dataset.rst
|
||||
|
||||
LFWPairs
|
||||
PhotoTour
|
||||
|
||||
Image captioning
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class_dataset.rst
|
||||
|
||||
CocoCaptions
|
||||
|
||||
Video classification
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class_dataset.rst
|
||||
|
||||
HMDB51
|
||||
Kinetics
|
||||
UCF101
|
||||
|
||||
Video prediction
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class_dataset.rst
|
||||
|
||||
MovingMNIST
|
||||
|
||||
.. _base_classes_datasets:
|
||||
|
||||
Base classes for custom datasets
|
||||
--------------------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class.rst
|
||||
|
||||
DatasetFolder
|
||||
ImageFolder
|
||||
VisionDataset
|
||||
|
||||
Transforms v2
|
||||
-------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
wrap_dataset_for_transforms_v2
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Necessary for the table generated by autosummary to look decent
|
||||
[html writers]
|
||||
table_style: colwidths-auto
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
Feature extraction for model inspection
|
||||
=======================================
|
||||
|
||||
.. currentmodule:: torchvision.models.feature_extraction
|
||||
|
||||
The ``torchvision.models.feature_extraction`` package contains
|
||||
feature extraction utilities that let us tap into our models to access intermediate
|
||||
transformations of our inputs. This could be useful for a variety of
|
||||
applications in computer vision. Just a few examples are:
|
||||
|
||||
- Visualizing feature maps.
|
||||
- Extracting features to compute image descriptors for tasks like facial
|
||||
recognition, copy-detection, or image retrieval.
|
||||
- Passing selected features to downstream sub-networks for end-to-end training
|
||||
with a specific task in mind. For example, passing a hierarchy of features
|
||||
to a Feature Pyramid Network with object detection heads.
|
||||
|
||||
Torchvision provides :func:`create_feature_extractor` for this purpose.
|
||||
It works by following roughly these steps:
|
||||
|
||||
1. Symbolically tracing the model to get a graphical representation of
|
||||
how it transforms the input, step by step.
|
||||
2. Setting the user-selected graph nodes as outputs.
|
||||
3. Removing all redundant nodes (anything downstream of the output nodes).
|
||||
4. Generating python code from the resulting graph and bundling that into a
|
||||
PyTorch module together with the graph itself.
|
||||
|
||||
|
|
||||
|
||||
The `torch.fx documentation <https://pytorch.org/docs/stable/fx.html>`_
|
||||
provides a more general and detailed explanation of the above procedure and
|
||||
the inner workings of the symbolic tracing.
|
||||
|
||||
.. _about-node-names:
|
||||
|
||||
**About Node Names**
|
||||
|
||||
In order to specify which nodes should be output nodes for extracted
|
||||
features, one should be familiar with the node naming convention used here
|
||||
(which differs slightly from that used in ``torch.fx``). A node name is
|
||||
specified as a ``.`` separated path walking the module hierarchy from top level
|
||||
module down to leaf operation or leaf module. For instance ``"layer4.2.relu"``
|
||||
in ResNet-50 represents the output of the ReLU of the 2nd block of the 4th
|
||||
layer of the ``ResNet`` module. Here are some finer points to keep in mind:
|
||||
|
||||
- When specifying node names for :func:`create_feature_extractor`, you may
|
||||
provide a truncated version of a node name as a shortcut. To see how this
|
||||
works, try creating a ResNet-50 model and printing the node names with
|
||||
``train_nodes, _ = get_graph_node_names(model) print(train_nodes)`` and
|
||||
observe that the last node pertaining to ``layer4`` is
|
||||
``"layer4.2.relu_2"``. One may specify ``"layer4.2.relu_2"`` as the return
|
||||
node, or just ``"layer4"`` as this, by convention, refers to the last node
|
||||
(in order of execution) of ``layer4``.
|
||||
- If a certain module or operation is repeated more than once, node names get
|
||||
an additional ``_{int}`` postfix to disambiguate. For instance, maybe the
|
||||
addition (``+``) operation is used three times in the same ``forward``
|
||||
method. Then there would be ``"path.to.module.add"``,
|
||||
``"path.to.module.add_1"``, ``"path.to.module.add_2"``. The counter is
|
||||
maintained within the scope of the direct parent. So in ResNet-50 there is
|
||||
a ``"layer4.1.add"`` and a ``"layer4.2.add"``. Because the addition
|
||||
operations reside in different blocks, there is no need for a postfix to
|
||||
disambiguate.
|
||||
|
||||
|
||||
**An Example**
|
||||
|
||||
Here is an example of how we might extract features for MaskRCNN:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import torch
|
||||
from torchvision.models import resnet50
|
||||
from torchvision.models.feature_extraction import get_graph_node_names
|
||||
from torchvision.models.feature_extraction import create_feature_extractor
|
||||
from torchvision.models.detection.mask_rcnn import MaskRCNN
|
||||
from torchvision.models.detection.backbone_utils import LastLevelMaxPool
|
||||
from torchvision.ops.feature_pyramid_network import FeaturePyramidNetwork
|
||||
|
||||
|
||||
# To assist you in designing the feature extractor you may want to print out
|
||||
# the available nodes for resnet50.
|
||||
m = resnet50()
|
||||
train_nodes, eval_nodes = get_graph_node_names(resnet50())
|
||||
|
||||
# The lists returned, are the names of all the graph nodes (in order of
|
||||
# execution) for the input model traced in train mode and in eval mode
|
||||
# respectively. You'll find that `train_nodes` and `eval_nodes` are the same
|
||||
# for this example. But if the model contains control flow that's dependent
|
||||
# on the training mode, they may be different.
|
||||
|
||||
# To specify the nodes you want to extract, you could select the final node
|
||||
# that appears in each of the main layers:
|
||||
return_nodes = {
|
||||
# node_name: user-specified key for output dict
|
||||
'layer1.2.relu_2': 'layer1',
|
||||
'layer2.3.relu_2': 'layer2',
|
||||
'layer3.5.relu_2': 'layer3',
|
||||
'layer4.2.relu_2': 'layer4',
|
||||
}
|
||||
|
||||
# But `create_feature_extractor` can also accept truncated node specifications
|
||||
# like "layer1", as it will just pick the last node that's a descendent of
|
||||
# of the specification. (Tip: be careful with this, especially when a layer
|
||||
# has multiple outputs. It's not always guaranteed that the last operation
|
||||
# performed is the one that corresponds to the output you desire. You should
|
||||
# consult the source code for the input model to confirm.)
|
||||
return_nodes = {
|
||||
'layer1': 'layer1',
|
||||
'layer2': 'layer2',
|
||||
'layer3': 'layer3',
|
||||
'layer4': 'layer4',
|
||||
}
|
||||
|
||||
# Now you can build the feature extractor. This returns a module whose forward
|
||||
# method returns a dictionary like:
|
||||
# {
|
||||
# 'layer1': output of layer 1,
|
||||
# 'layer2': output of layer 2,
|
||||
# 'layer3': output of layer 3,
|
||||
# 'layer4': output of layer 4,
|
||||
# }
|
||||
create_feature_extractor(m, return_nodes=return_nodes)
|
||||
|
||||
# Let's put all that together to wrap resnet50 with MaskRCNN
|
||||
|
||||
# MaskRCNN requires a backbone with an attached FPN
|
||||
class Resnet50WithFPN(torch.nn.Module):
|
||||
def __init__(self):
|
||||
super(Resnet50WithFPN, self).__init__()
|
||||
# Get a resnet50 backbone
|
||||
m = resnet50()
|
||||
# Extract 4 main layers (note: MaskRCNN needs this particular name
|
||||
# mapping for return nodes)
|
||||
self.body = create_feature_extractor(
|
||||
m, return_nodes={f'layer{k}': str(v)
|
||||
for v, k in enumerate([1, 2, 3, 4])})
|
||||
# Dry run to get number of channels for FPN
|
||||
inp = torch.randn(2, 3, 224, 224)
|
||||
with torch.no_grad():
|
||||
out = self.body(inp)
|
||||
in_channels_list = [o.shape[1] for o in out.values()]
|
||||
# Build FPN
|
||||
self.out_channels = 256
|
||||
self.fpn = FeaturePyramidNetwork(
|
||||
in_channels_list, out_channels=self.out_channels,
|
||||
extra_blocks=LastLevelMaxPool())
|
||||
|
||||
def forward(self, x):
|
||||
x = self.body(x)
|
||||
x = self.fpn(x)
|
||||
return x
|
||||
|
||||
|
||||
# Now we can build our model!
|
||||
model = MaskRCNN(Resnet50WithFPN(), num_classes=91).eval()
|
||||
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
create_feature_extractor
|
||||
get_graph_node_names
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
torchvision
|
||||
===========
|
||||
This library is part of the `PyTorch
|
||||
<http://pytorch.org/>`_ project. PyTorch is an open source
|
||||
machine learning framework.
|
||||
|
||||
Features described in this documentation are classified by release status:
|
||||
|
||||
*Stable:* These features will be maintained long-term and there should generally
|
||||
be no major performance limitations or gaps in documentation.
|
||||
We also expect to maintain backwards compatibility (although
|
||||
breaking changes can happen and notice will be given one release ahead
|
||||
of time).
|
||||
|
||||
*Beta:* Features are tagged as Beta because the API may change based on
|
||||
user feedback, because the performance needs to improve, or because
|
||||
coverage across operators is not yet complete. For Beta features, we are
|
||||
committing to seeing the feature through to the Stable classification.
|
||||
We are not, however, committing to backwards compatibility.
|
||||
|
||||
*Prototype:* These features are typically not available as part of
|
||||
binary distributions like PyPI or Conda, except sometimes behind run-time
|
||||
flags, and are at an early stage for feedback and testing.
|
||||
|
||||
|
||||
|
||||
The :mod:`torchvision` package consists of popular datasets, model
|
||||
architectures, and common image transformations for computer vision.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Package Reference
|
||||
|
||||
transforms
|
||||
tv_tensors
|
||||
models
|
||||
datasets
|
||||
utils
|
||||
ops
|
||||
io
|
||||
feature_extraction
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Examples and training references
|
||||
|
||||
auto_examples/index
|
||||
training_references
|
||||
|
||||
.. automodule:: torchvision
|
||||
:members:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: PyTorch Libraries
|
||||
|
||||
PyTorch <https://pytorch.org/docs>
|
||||
torchaudio <https://pytorch.org/audio>
|
||||
torchtext <https://pytorch.org/text>
|
||||
torchvision <https://pytorch.org/vision>
|
||||
TorchElastic <https://pytorch.org/elastic/>
|
||||
TorchServe <https://pytorch.org/serve>
|
||||
PyTorch on XLA Devices <http://pytorch.org/xla/>
|
||||
|
||||
|
||||
Indices
|
||||
-------
|
||||
|
||||
* :ref:`genindex`
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
Decoding / Encoding images and videos
|
||||
=====================================
|
||||
|
||||
.. currentmodule:: torchvision.io
|
||||
|
||||
The :mod:`torchvision.io` module provides utilities for decoding and encoding
|
||||
images and videos.
|
||||
|
||||
Image Decoding
|
||||
--------------
|
||||
|
||||
Torchvision currently supports decoding JPEG, PNG, WEBP, GIF, AVIF, and HEIC
|
||||
images. JPEG decoding can also be done on CUDA GPUs.
|
||||
|
||||
The main entry point is the :func:`~torchvision.io.decode_image` function, which
|
||||
you can use as an alternative to ``PIL.Image.open()``. It will decode images
|
||||
straight into image Tensors, thus saving you the conversion and allowing you to
|
||||
run transforms/preproc natively on tensors.
|
||||
|
||||
.. code::
|
||||
|
||||
from torchvision.io import decode_image
|
||||
|
||||
img = decode_image("path_to_image", mode="RGB")
|
||||
img.dtype # torch.uint8
|
||||
|
||||
# Or
|
||||
raw_encoded_bytes = ... # read encoded bytes from your file system
|
||||
img = decode_image(raw_encoded_bytes, mode="RGB")
|
||||
|
||||
|
||||
:func:`~torchvision.io.decode_image` will automatically detect the image format,
|
||||
and call the corresponding decoder (except for HEIC and AVIF images, see details
|
||||
in :func:`~torchvision.io.decode_avif` and :func:`~torchvision.io.decode_heic`).
|
||||
You can also use the lower-level format-specific decoders which can be more
|
||||
powerful, e.g. if you want to encode/decode JPEGs on CUDA.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
decode_image
|
||||
decode_jpeg
|
||||
decode_png
|
||||
decode_webp
|
||||
decode_avif
|
||||
decode_heic
|
||||
decode_gif
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class.rst
|
||||
|
||||
ImageReadMode
|
||||
|
||||
Obsolete decoding function:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
read_image
|
||||
|
||||
Image Encoding
|
||||
--------------
|
||||
|
||||
For encoding, JPEG (cpu and CUDA) and PNG are supported.
|
||||
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
encode_jpeg
|
||||
write_jpeg
|
||||
encode_png
|
||||
write_png
|
||||
|
||||
IO operations
|
||||
-------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
read_file
|
||||
write_file
|
||||
|
||||
Video - DEPREACTED
|
||||
------------------
|
||||
|
||||
.. warning::
|
||||
|
||||
DEPRECATED: All the video decoding and encoding capabilities of torchvision
|
||||
are deprecated from version 0.22 and will be removed in version 0.24. We
|
||||
recommend that you migrate to
|
||||
`TorchCodec <https://github.com/pytorch/torchcodec>`__, where we'll
|
||||
consolidate the future decoding/encoding capabilities of PyTorch
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
read_video
|
||||
read_video_timestamps
|
||||
write_video
|
||||
|
||||
|
||||
**Fine-grained video API**
|
||||
|
||||
In addition to the :mod:`read_video` function, we provide a high-performance
|
||||
lower-level API for more fine-grained control compared to the :mod:`read_video` function.
|
||||
It does all this whilst fully supporting torchscript.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: class.rst
|
||||
|
||||
VideoReader
|
||||
|
|
@ -0,0 +1,577 @@
|
|||
.. _models:
|
||||
|
||||
Models and pre-trained weights
|
||||
##############################
|
||||
|
||||
The ``torchvision.models`` subpackage contains definitions of models for addressing
|
||||
different tasks, including: image classification, pixelwise semantic
|
||||
segmentation, object detection, instance segmentation, person
|
||||
keypoint detection, video classification, and optical flow.
|
||||
|
||||
General information on pre-trained weights
|
||||
==========================================
|
||||
|
||||
TorchVision offers pre-trained weights for every provided architecture, using
|
||||
the PyTorch :mod:`torch.hub`. Instancing a pre-trained model will download its
|
||||
weights to a cache directory. This directory can be set using the `TORCH_HOME`
|
||||
environment variable. See :func:`torch.hub.load_state_dict_from_url` for details.
|
||||
|
||||
.. note::
|
||||
|
||||
The pre-trained models provided in this library may have their own licenses or
|
||||
terms and conditions derived from the dataset used for training. It is your
|
||||
responsibility to determine whether you have permission to use the models for
|
||||
your use case.
|
||||
|
||||
.. note ::
|
||||
Backward compatibility is guaranteed for loading a serialized
|
||||
``state_dict`` to the model created using old PyTorch version.
|
||||
On the contrary, loading entire saved models or serialized
|
||||
``ScriptModules`` (serialized using older versions of PyTorch)
|
||||
may not preserve the historic behaviour. Refer to the following
|
||||
`documentation
|
||||
<https://pytorch.org/docs/stable/notes/serialization.html#id6>`_
|
||||
|
||||
|
||||
Initializing pre-trained models
|
||||
-------------------------------
|
||||
|
||||
As of v0.13, TorchVision offers a new `Multi-weight support API
|
||||
<https://pytorch.org/blog/introducing-torchvision-new-multi-weight-support-api/>`_
|
||||
for loading different weights to the existing model builder methods:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from torchvision.models import resnet50, ResNet50_Weights
|
||||
|
||||
# Old weights with accuracy 76.130%
|
||||
resnet50(weights=ResNet50_Weights.IMAGENET1K_V1)
|
||||
|
||||
# New weights with accuracy 80.858%
|
||||
resnet50(weights=ResNet50_Weights.IMAGENET1K_V2)
|
||||
|
||||
# Best available weights (currently alias for IMAGENET1K_V2)
|
||||
# Note that these weights may change across versions
|
||||
resnet50(weights=ResNet50_Weights.DEFAULT)
|
||||
|
||||
# Strings are also supported
|
||||
resnet50(weights="IMAGENET1K_V2")
|
||||
|
||||
# No weights - random initialization
|
||||
resnet50(weights=None)
|
||||
|
||||
|
||||
Migrating to the new API is very straightforward. The following method calls between the 2 APIs are all equivalent:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from torchvision.models import resnet50, ResNet50_Weights
|
||||
|
||||
# Using pretrained weights:
|
||||
resnet50(weights=ResNet50_Weights.IMAGENET1K_V1)
|
||||
resnet50(weights="IMAGENET1K_V1")
|
||||
resnet50(pretrained=True) # deprecated
|
||||
resnet50(True) # deprecated
|
||||
|
||||
# Using no weights:
|
||||
resnet50(weights=None)
|
||||
resnet50()
|
||||
resnet50(pretrained=False) # deprecated
|
||||
resnet50(False) # deprecated
|
||||
|
||||
Note that the ``pretrained`` parameter is now deprecated, using it will emit warnings and will be removed on v0.15.
|
||||
|
||||
Using the pre-trained models
|
||||
----------------------------
|
||||
|
||||
Before using the pre-trained models, one must preprocess the image
|
||||
(resize with right resolution/interpolation, apply inference transforms,
|
||||
rescale the values etc). There is no standard way to do this as it depends on
|
||||
how a given model was trained. It can vary across model families, variants or
|
||||
even weight versions. Using the correct preprocessing method is critical and
|
||||
failing to do so may lead to decreased accuracy or incorrect outputs.
|
||||
|
||||
All the necessary information for the inference transforms of each pre-trained
|
||||
model is provided on its weights documentation. To simplify inference, TorchVision
|
||||
bundles the necessary preprocessing transforms into each model weight. These are
|
||||
accessible via the ``weight.transforms`` attribute:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Initialize the Weight Transforms
|
||||
weights = ResNet50_Weights.DEFAULT
|
||||
preprocess = weights.transforms()
|
||||
|
||||
# Apply it to the input image
|
||||
img_transformed = preprocess(img)
|
||||
|
||||
|
||||
Some models use modules which have different training and evaluation
|
||||
behavior, such as batch normalization. To switch between these modes, use
|
||||
``model.train()`` or ``model.eval()`` as appropriate. See
|
||||
:meth:`~torch.nn.Module.train` or :meth:`~torch.nn.Module.eval` for details.
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Initialize model
|
||||
weights = ResNet50_Weights.DEFAULT
|
||||
model = resnet50(weights=weights)
|
||||
|
||||
# Set model to eval mode
|
||||
model.eval()
|
||||
|
||||
Listing and retrieving available models
|
||||
---------------------------------------
|
||||
|
||||
As of v0.14, TorchVision offers a new mechanism which allows listing and
|
||||
retrieving models and weights by their names. Here are a few examples on how to
|
||||
use them:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# List available models
|
||||
all_models = list_models()
|
||||
classification_models = list_models(module=torchvision.models)
|
||||
|
||||
# Initialize models
|
||||
m1 = get_model("mobilenet_v3_large", weights=None)
|
||||
m2 = get_model("quantized_mobilenet_v3_large", weights="DEFAULT")
|
||||
|
||||
# Fetch weights
|
||||
weights = get_weight("MobileNet_V3_Large_QuantizedWeights.DEFAULT")
|
||||
assert weights == MobileNet_V3_Large_QuantizedWeights.DEFAULT
|
||||
|
||||
weights_enum = get_model_weights("quantized_mobilenet_v3_large")
|
||||
assert weights_enum == MobileNet_V3_Large_QuantizedWeights
|
||||
|
||||
weights_enum2 = get_model_weights(torchvision.models.quantization.mobilenet_v3_large)
|
||||
assert weights_enum == weights_enum2
|
||||
|
||||
Here are the available public functions to retrieve models and their corresponding weights:
|
||||
|
||||
.. currentmodule:: torchvision.models
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
get_model
|
||||
get_model_weights
|
||||
get_weight
|
||||
list_models
|
||||
|
||||
Using models from Hub
|
||||
---------------------
|
||||
|
||||
Most pre-trained models can be accessed directly via PyTorch Hub without having TorchVision installed:
|
||||
|
||||
.. code:: python
|
||||
|
||||
import torch
|
||||
|
||||
# Option 1: passing weights param as string
|
||||
model = torch.hub.load("pytorch/vision", "resnet50", weights="IMAGENET1K_V2")
|
||||
|
||||
# Option 2: passing weights param as enum
|
||||
weights = torch.hub.load(
|
||||
"pytorch/vision",
|
||||
"get_weight",
|
||||
weights="ResNet50_Weights.IMAGENET1K_V2",
|
||||
)
|
||||
model = torch.hub.load("pytorch/vision", "resnet50", weights=weights)
|
||||
|
||||
You can also retrieve all the available weights of a specific model via PyTorch Hub by doing:
|
||||
|
||||
.. code:: python
|
||||
|
||||
import torch
|
||||
|
||||
weight_enum = torch.hub.load("pytorch/vision", "get_model_weights", name="resnet50")
|
||||
print([weight for weight in weight_enum])
|
||||
|
||||
The only exception to the above are the detection models included on
|
||||
:mod:`torchvision.models.detection`. These models require TorchVision
|
||||
to be installed because they depend on custom C++ operators.
|
||||
|
||||
Classification
|
||||
==============
|
||||
|
||||
.. currentmodule:: torchvision.models
|
||||
|
||||
The following classification models are available, with or without pre-trained
|
||||
weights:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
models/alexnet
|
||||
models/convnext
|
||||
models/densenet
|
||||
models/efficientnet
|
||||
models/efficientnetv2
|
||||
models/googlenet
|
||||
models/inception
|
||||
models/maxvit
|
||||
models/mnasnet
|
||||
models/mobilenetv2
|
||||
models/mobilenetv3
|
||||
models/regnet
|
||||
models/resnet
|
||||
models/resnext
|
||||
models/shufflenetv2
|
||||
models/squeezenet
|
||||
models/swin_transformer
|
||||
models/vgg
|
||||
models/vision_transformer
|
||||
models/wide_resnet
|
||||
|
||||
|
|
||||
|
||||
Here is an example of how to use the pre-trained image classification models:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from torchvision.io import decode_image
|
||||
from torchvision.models import resnet50, ResNet50_Weights
|
||||
|
||||
img = decode_image("test/assets/encode_jpeg/grace_hopper_517x606.jpg")
|
||||
|
||||
# Step 1: Initialize model with the best available weights
|
||||
weights = ResNet50_Weights.DEFAULT
|
||||
model = resnet50(weights=weights)
|
||||
model.eval()
|
||||
|
||||
# Step 2: Initialize the inference transforms
|
||||
preprocess = weights.transforms()
|
||||
|
||||
# Step 3: Apply inference preprocessing transforms
|
||||
batch = preprocess(img).unsqueeze(0)
|
||||
|
||||
# Step 4: Use the model and print the predicted category
|
||||
prediction = model(batch).squeeze(0).softmax(0)
|
||||
class_id = prediction.argmax().item()
|
||||
score = prediction[class_id].item()
|
||||
category_name = weights.meta["categories"][class_id]
|
||||
print(f"{category_name}: {100 * score:.1f}%")
|
||||
|
||||
The classes of the pre-trained model outputs can be found at ``weights.meta["categories"]``.
|
||||
|
||||
Table of all available classification weights
|
||||
---------------------------------------------
|
||||
|
||||
Accuracies are reported on ImageNet-1K using single crops:
|
||||
|
||||
.. include:: generated/classification_table.rst
|
||||
|
||||
Quantized models
|
||||
----------------
|
||||
|
||||
.. currentmodule:: torchvision.models.quantization
|
||||
|
||||
The following architectures provide support for INT8 quantized models, with or without
|
||||
pre-trained weights:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
models/googlenet_quant
|
||||
models/inception_quant
|
||||
models/mobilenetv2_quant
|
||||
models/mobilenetv3_quant
|
||||
models/resnet_quant
|
||||
models/resnext_quant
|
||||
models/shufflenetv2_quant
|
||||
|
||||
|
|
||||
|
||||
Here is an example of how to use the pre-trained quantized image classification models:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from torchvision.io import decode_image
|
||||
from torchvision.models.quantization import resnet50, ResNet50_QuantizedWeights
|
||||
|
||||
img = decode_image("test/assets/encode_jpeg/grace_hopper_517x606.jpg")
|
||||
|
||||
# Step 1: Initialize model with the best available weights
|
||||
weights = ResNet50_QuantizedWeights.DEFAULT
|
||||
model = resnet50(weights=weights, quantize=True)
|
||||
model.eval()
|
||||
|
||||
# Step 2: Initialize the inference transforms
|
||||
preprocess = weights.transforms()
|
||||
|
||||
# Step 3: Apply inference preprocessing transforms
|
||||
batch = preprocess(img).unsqueeze(0)
|
||||
|
||||
# Step 4: Use the model and print the predicted category
|
||||
prediction = model(batch).squeeze(0).softmax(0)
|
||||
class_id = prediction.argmax().item()
|
||||
score = prediction[class_id].item()
|
||||
category_name = weights.meta["categories"][class_id]
|
||||
print(f"{category_name}: {100 * score}%")
|
||||
|
||||
The classes of the pre-trained model outputs can be found at ``weights.meta["categories"]``.
|
||||
|
||||
|
||||
Table of all available quantized classification weights
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Accuracies are reported on ImageNet-1K using single crops:
|
||||
|
||||
.. include:: generated/classification_quant_table.rst
|
||||
|
||||
Semantic Segmentation
|
||||
=====================
|
||||
|
||||
.. currentmodule:: torchvision.models.segmentation
|
||||
|
||||
.. betastatus:: segmentation module
|
||||
|
||||
The following semantic segmentation models are available, with or without
|
||||
pre-trained weights:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
models/deeplabv3
|
||||
models/fcn
|
||||
models/lraspp
|
||||
|
||||
|
|
||||
|
||||
Here is an example of how to use the pre-trained semantic segmentation models:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from torchvision.io.image import decode_image
|
||||
from torchvision.models.segmentation import fcn_resnet50, FCN_ResNet50_Weights
|
||||
from torchvision.transforms.functional import to_pil_image
|
||||
|
||||
img = decode_image("gallery/assets/dog1.jpg")
|
||||
|
||||
# Step 1: Initialize model with the best available weights
|
||||
weights = FCN_ResNet50_Weights.DEFAULT
|
||||
model = fcn_resnet50(weights=weights)
|
||||
model.eval()
|
||||
|
||||
# Step 2: Initialize the inference transforms
|
||||
preprocess = weights.transforms()
|
||||
|
||||
# Step 3: Apply inference preprocessing transforms
|
||||
batch = preprocess(img).unsqueeze(0)
|
||||
|
||||
# Step 4: Use the model and visualize the prediction
|
||||
prediction = model(batch)["out"]
|
||||
normalized_masks = prediction.softmax(dim=1)
|
||||
class_to_idx = {cls: idx for (idx, cls) in enumerate(weights.meta["categories"])}
|
||||
mask = normalized_masks[0, class_to_idx["dog"]]
|
||||
to_pil_image(mask).show()
|
||||
|
||||
The classes of the pre-trained model outputs can be found at ``weights.meta["categories"]``.
|
||||
The output format of the models is illustrated in :ref:`semantic_seg_output`.
|
||||
|
||||
|
||||
Table of all available semantic segmentation weights
|
||||
----------------------------------------------------
|
||||
|
||||
All models are evaluated a subset of COCO val2017, on the 20 categories that are present in the Pascal VOC dataset:
|
||||
|
||||
.. include:: generated/segmentation_table.rst
|
||||
|
||||
|
||||
.. _object_det_inst_seg_pers_keypoint_det:
|
||||
|
||||
Object Detection, Instance Segmentation and Person Keypoint Detection
|
||||
=====================================================================
|
||||
|
||||
The pre-trained models for detection, instance segmentation and
|
||||
keypoint detection are initialized with the classification models
|
||||
in torchvision. The models expect a list of ``Tensor[C, H, W]``.
|
||||
Check the constructor of the models for more information.
|
||||
|
||||
.. betastatus:: detection module
|
||||
|
||||
Object Detection
|
||||
----------------
|
||||
|
||||
.. currentmodule:: torchvision.models.detection
|
||||
|
||||
The following object detection models are available, with or without pre-trained
|
||||
weights:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
models/faster_rcnn
|
||||
models/fcos
|
||||
models/retinanet
|
||||
models/ssd
|
||||
models/ssdlite
|
||||
|
||||
|
|
||||
|
||||
Here is an example of how to use the pre-trained object detection models:
|
||||
|
||||
.. code:: python
|
||||
|
||||
|
||||
from torchvision.io.image import decode_image
|
||||
from torchvision.models.detection import fasterrcnn_resnet50_fpn_v2, FasterRCNN_ResNet50_FPN_V2_Weights
|
||||
from torchvision.utils import draw_bounding_boxes
|
||||
from torchvision.transforms.functional import to_pil_image
|
||||
|
||||
img = decode_image("test/assets/encode_jpeg/grace_hopper_517x606.jpg")
|
||||
|
||||
# Step 1: Initialize model with the best available weights
|
||||
weights = FasterRCNN_ResNet50_FPN_V2_Weights.DEFAULT
|
||||
model = fasterrcnn_resnet50_fpn_v2(weights=weights, box_score_thresh=0.9)
|
||||
model.eval()
|
||||
|
||||
# Step 2: Initialize the inference transforms
|
||||
preprocess = weights.transforms()
|
||||
|
||||
# Step 3: Apply inference preprocessing transforms
|
||||
batch = [preprocess(img)]
|
||||
|
||||
# Step 4: Use the model and visualize the prediction
|
||||
prediction = model(batch)[0]
|
||||
labels = [weights.meta["categories"][i] for i in prediction["labels"]]
|
||||
box = draw_bounding_boxes(img, boxes=prediction["boxes"],
|
||||
labels=labels,
|
||||
colors="red",
|
||||
width=4, font_size=30)
|
||||
im = to_pil_image(box.detach())
|
||||
im.show()
|
||||
|
||||
The classes of the pre-trained model outputs can be found at ``weights.meta["categories"]``.
|
||||
For details on how to plot the bounding boxes of the models, you may refer to :ref:`instance_seg_output`.
|
||||
|
||||
Table of all available Object detection weights
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Box MAPs are reported on COCO val2017:
|
||||
|
||||
.. include:: generated/detection_table.rst
|
||||
|
||||
|
||||
Instance Segmentation
|
||||
---------------------
|
||||
|
||||
.. currentmodule:: torchvision.models.detection
|
||||
|
||||
The following instance segmentation models are available, with or without pre-trained
|
||||
weights:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
models/mask_rcnn
|
||||
|
||||
|
|
||||
|
||||
|
||||
For details on how to plot the masks of the models, you may refer to :ref:`instance_seg_output`.
|
||||
|
||||
Table of all available Instance segmentation weights
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Box and Mask MAPs are reported on COCO val2017:
|
||||
|
||||
.. include:: generated/instance_segmentation_table.rst
|
||||
|
||||
Keypoint Detection
|
||||
------------------
|
||||
|
||||
.. currentmodule:: torchvision.models.detection
|
||||
|
||||
The following person keypoint detection models are available, with or without
|
||||
pre-trained weights:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
models/keypoint_rcnn
|
||||
|
||||
|
|
||||
|
||||
The classes of the pre-trained model outputs can be found at ``weights.meta["keypoint_names"]``.
|
||||
For details on how to plot the bounding boxes of the models, you may refer to :ref:`keypoint_output`.
|
||||
|
||||
Table of all available Keypoint detection weights
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Box and Keypoint MAPs are reported on COCO val2017:
|
||||
|
||||
.. include:: generated/detection_keypoint_table.rst
|
||||
|
||||
|
||||
Video Classification
|
||||
====================
|
||||
|
||||
.. currentmodule:: torchvision.models.video
|
||||
|
||||
.. betastatus:: video module
|
||||
|
||||
The following video classification models are available, with or without
|
||||
pre-trained weights:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
models/video_mvit
|
||||
models/video_resnet
|
||||
models/video_s3d
|
||||
models/video_swin_transformer
|
||||
|
||||
|
|
||||
|
||||
Here is an example of how to use the pre-trained video classification models:
|
||||
|
||||
.. code:: python
|
||||
|
||||
|
||||
from torchvision.io.video import read_video
|
||||
from torchvision.models.video import r3d_18, R3D_18_Weights
|
||||
|
||||
vid, _, _ = read_video("test/assets/videos/v_SoccerJuggling_g23_c01.avi", output_format="TCHW")
|
||||
vid = vid[:32] # optionally shorten duration
|
||||
|
||||
# Step 1: Initialize model with the best available weights
|
||||
weights = R3D_18_Weights.DEFAULT
|
||||
model = r3d_18(weights=weights)
|
||||
model.eval()
|
||||
|
||||
# Step 2: Initialize the inference transforms
|
||||
preprocess = weights.transforms()
|
||||
|
||||
# Step 3: Apply inference preprocessing transforms
|
||||
batch = preprocess(vid).unsqueeze(0)
|
||||
|
||||
# Step 4: Use the model and print the predicted category
|
||||
prediction = model(batch).squeeze(0).softmax(0)
|
||||
label = prediction.argmax().item()
|
||||
score = prediction[label].item()
|
||||
category_name = weights.meta["categories"][label]
|
||||
print(f"{category_name}: {100 * score}%")
|
||||
|
||||
The classes of the pre-trained model outputs can be found at ``weights.meta["categories"]``.
|
||||
|
||||
|
||||
Table of all available video classification weights
|
||||
---------------------------------------------------
|
||||
|
||||
Accuracies are reported on Kinetics-400 using single crops for clip length 16:
|
||||
|
||||
.. include:: generated/video_table.rst
|
||||
|
||||
Optical Flow
|
||||
============
|
||||
|
||||
.. currentmodule:: torchvision.models.optical_flow
|
||||
|
||||
The following Optical Flow models are available, with or without pre-trained
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
models/raft
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
AlexNet
|
||||
=======
|
||||
|
||||
.. currentmodule:: torchvision.models
|
||||
|
||||
The AlexNet model was originally introduced in the
|
||||
`ImageNet Classification with Deep Convolutional Neural Networks
|
||||
<https://papers.nips.cc/paper/2012/hash/c399862d3b9d6b76c8436e924a68c45b-Abstract.html>`__
|
||||
paper. The implemented architecture is slightly different from the original one,
|
||||
and is based on `One weird trick for parallelizing convolutional neural networks
|
||||
<https://arxiv.org/abs/1404.5997>`__.
|
||||
|
||||
|
||||
Model builders
|
||||
--------------
|
||||
|
||||
The following model builders can be used to instantiate an AlexNet model, with or
|
||||
without pre-trained weights. All the model builders internally rely on the
|
||||
``torchvision.models.alexnet.AlexNet`` base class. Please refer to the `source
|
||||
code
|
||||
<https://github.com/pytorch/vision/blob/main/torchvision/models/alexnet.py>`_ for
|
||||
more details about this class.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
alexnet
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
ConvNeXt
|
||||
========
|
||||
|
||||
.. currentmodule:: torchvision.models
|
||||
|
||||
The ConvNeXt model is based on the `A ConvNet for the 2020s
|
||||
<https://arxiv.org/abs/2201.03545>`_ paper.
|
||||
|
||||
|
||||
Model builders
|
||||
--------------
|
||||
|
||||
The following model builders can be used to instantiate a ConvNeXt model, with or
|
||||
without pre-trained weights. All the model builders internally rely on the
|
||||
``torchvision.models.convnext.ConvNeXt`` base class. Please refer to the `source code
|
||||
<https://github.com/pytorch/vision/blob/main/torchvision/models/convnext.py>`_ for
|
||||
more details about this class.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
convnext_tiny
|
||||
convnext_small
|
||||
convnext_base
|
||||
convnext_large
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
DeepLabV3
|
||||
=========
|
||||
|
||||
.. currentmodule:: torchvision.models.segmentation
|
||||
|
||||
The DeepLabV3 model is based on the `Rethinking Atrous Convolution for Semantic
|
||||
Image Segmentation <https://arxiv.org/abs/1706.05587>`__ paper.
|
||||
|
||||
.. betastatus:: segmentation module
|
||||
|
||||
|
||||
Model builders
|
||||
--------------
|
||||
|
||||
The following model builders can be used to instantiate a DeepLabV3 model with
|
||||
different backbones, with or without pre-trained weights. All the model builders
|
||||
internally rely on the ``torchvision.models.segmentation.deeplabv3.DeepLabV3`` base class. Please
|
||||
refer to the `source code
|
||||
<https://github.com/pytorch/vision/blob/main/torchvision/models/segmentation/deeplabv3.py>`_
|
||||
for more details about this class.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
deeplabv3_mobilenet_v3_large
|
||||
deeplabv3_resnet50
|
||||
deeplabv3_resnet101
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
DenseNet
|
||||
========
|
||||
|
||||
.. currentmodule:: torchvision.models
|
||||
|
||||
The DenseNet model is based on the `Densely Connected Convolutional Networks
|
||||
<https://arxiv.org/abs/1608.06993>`_ paper.
|
||||
|
||||
|
||||
Model builders
|
||||
--------------
|
||||
|
||||
The following model builders can be used to instantiate a DenseNet model, with or
|
||||
without pre-trained weights. All the model builders internally rely on the
|
||||
``torchvision.models.densenet.DenseNet`` base class. Please refer to the `source
|
||||
code
|
||||
<https://github.com/pytorch/vision/blob/main/torchvision/models/densenet.py>`_ for
|
||||
more details about this class.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
densenet121
|
||||
densenet161
|
||||
densenet169
|
||||
densenet201
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
EfficientNet
|
||||
============
|
||||
|
||||
.. currentmodule:: torchvision.models
|
||||
|
||||
The EfficientNet model is based on the `EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks <https://arxiv.org/abs/1905.11946>`__
|
||||
paper.
|
||||
|
||||
|
||||
Model builders
|
||||
--------------
|
||||
|
||||
The following model builders can be used to instantiate an EfficientNet model, with or
|
||||
without pre-trained weights. All the model builders internally rely on the
|
||||
``torchvision.models.efficientnet.EfficientNet`` base class. Please refer to the `source
|
||||
code
|
||||
<https://github.com/pytorch/vision/blob/main/torchvision/models/efficientnet.py>`_ for
|
||||
more details about this class.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
efficientnet_b0
|
||||
efficientnet_b1
|
||||
efficientnet_b2
|
||||
efficientnet_b3
|
||||
efficientnet_b4
|
||||
efficientnet_b5
|
||||
efficientnet_b6
|
||||
efficientnet_b7
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
EfficientNetV2
|
||||
==============
|
||||
|
||||
.. currentmodule:: torchvision.models
|
||||
|
||||
The EfficientNetV2 model is based on the `EfficientNetV2: Smaller Models and Faster Training <https://arxiv.org/abs/2104.00298>`__
|
||||
paper.
|
||||
|
||||
|
||||
Model builders
|
||||
--------------
|
||||
|
||||
The following model builders can be used to instantiate an EfficientNetV2 model, with or
|
||||
without pre-trained weights. All the model builders internally rely on the
|
||||
``torchvision.models.efficientnet.EfficientNet`` base class. Please refer to the `source
|
||||
code
|
||||
<https://github.com/pytorch/vision/blob/main/torchvision/models/efficientnet.py>`_ for
|
||||
more details about this class.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated/
|
||||
:template: function.rst
|
||||
|
||||
efficientnet_v2_s
|
||||
efficientnet_v2_m
|
||||
efficientnet_v2_l
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue