Skip to content

Commit 2d3c99b

Browse files
committed
Merge branch 'main' of github.com:pytorch/vision into tv-tensor-enhance
2 parents 1cfe17d + 2ae6a6d commit 2d3c99b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+1169
-540
lines changed

.github/workflows/prototype-tests-linux-gpu.yml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ jobs:
1212
- "3.9"
1313
- "3.10"
1414
- "3.11"
15+
- "3.12"
1516
runner: ["linux.12xlarge"]
1617
gpu-arch-type: ["cpu"]
1718
include:

.github/workflows/tests-schedule.yml

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ jobs:
2929
- name: Checkout repository
3030
uses: actions/checkout@v2
3131

32+
- name: TODO REMOVE THIS! Install non pre-release version of mpmath.
33+
run: pip install "mpmath<1.4"
34+
3235
- name: Install torch nightly build
3336
run: pip install --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html
3437

.github/workflows/tests.yml

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ jobs:
1818
- "3.9"
1919
- "3.10"
2020
- "3.11"
21+
- "3.12"
2122
runner: ["linux.12xlarge"]
2223
gpu-arch-type: ["cpu"]
2324
include:
@@ -51,6 +52,7 @@ jobs:
5152
- "3.9"
5253
- "3.10"
5354
- "3.11"
55+
- "3.12"
5456
runner: ["macos-12"]
5557
include:
5658
- python-version: "3.8"
@@ -81,6 +83,7 @@ jobs:
8183
- "3.9"
8284
- "3.10"
8385
- "3.11"
86+
- "3.12"
8487
runner: ["windows.4xlarge"]
8588
gpu-arch-type: ["cpu"]
8689
include:

docs/source/models/ssdlite.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ The following model builders can be used to instantiate a SSD Lite model, with o
1717
without pre-trained weights. All the model builders internally rely on the
1818
``torchvision.models.detection.ssd.SSD`` base class. Please refer to the `source
1919
code
20-
<https://github.com/pytorch/vision/blob/main/torchvision/models/detection/ssd.py>`_ for
20+
<https://github.com/pytorch/vision/blob/main/torchvision/models/detection/ssdlite.py>`_ for
2121
more details about this class.
2222

2323
.. autosummary::

docs/source/transforms.rst

+6-1
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ Color
347347
v2.RandomChannelPermutation
348348
v2.RandomPhotometricDistort
349349
v2.Grayscale
350+
v2.RGB
350351
v2.RandomGrayscale
351352
v2.GaussianBlur
352353
v2.RandomInvert
@@ -364,6 +365,7 @@ Functionals
364365

365366
v2.functional.permute_channels
366367
v2.functional.rgb_to_grayscale
368+
v2.functional.grayscale_to_rgb
367369
v2.functional.to_grayscale
368370
v2.functional.gaussian_blur
369371
v2.functional.invert
@@ -405,6 +407,7 @@ Miscellaneous
405407
v2.SanitizeBoundingBoxes
406408
v2.ClampBoundingBoxes
407409
v2.UniformTemporalSubsample
410+
v2.JPEG
408411

409412
Functionals
410413

@@ -414,8 +417,10 @@ Functionals
414417

415418
v2.functional.normalize
416419
v2.functional.erase
420+
v2.functional.sanitize_bounding_boxes
417421
v2.functional.clamp_bounding_boxes
418422
v2.functional.uniform_temporal_subsample
423+
v2.functional.jpeg
419424

420425
.. _conversion_transforms:
421426

@@ -583,7 +588,7 @@ Conversion
583588
while performing the conversion, while some may not do any scaling. By
584589
scaling, we mean e.g. that a ``uint8`` -> ``float32`` would map the [0,
585590
255] range into [0, 1] (and vice-versa). See :ref:`range_and_dtype`.
586-
591+
587592
.. autosummary::
588593
:toctree: generated/
589594
:template: class.rst

gallery/transforms/plot_transforms_e2e.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@
151151
# We need a custom collation function here, since the object detection
152152
# models expect a sequence of images and target dictionaries. The default
153153
# collation function tries to torch.stack() the individual elements,
154-
# which fails in general for object detection, because the number of bouding
155-
# boxes varies between the images of a same batch.
154+
# which fails in general for object detection, because the number of bounding
155+
# boxes varies between the images of the same batch.
156156
collate_fn=lambda batch: tuple(zip(*batch)),
157157
)
158158

gallery/transforms/plot_transforms_illustrations.py

+11
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,17 @@
237237
equalized_imgs = [equalizer(orig_img) for _ in range(4)]
238238
plot([orig_img] + equalized_imgs)
239239

240+
# %%
241+
# JPEG
242+
# ~~~~~~~~~~~~~~
243+
# The :class:`~torchvision.transforms.v2.JPEG` transform
244+
# (see also :func:`~torchvision.transforms.v2.functional.jpeg`)
245+
# applies JPEG compression to the given image with random
246+
# degree of compression.
247+
jpeg = v2.JPEG((5, 50))
248+
jpeg_imgs = [jpeg(orig_img) for _ in range(4)]
249+
plot([orig_img] + jpeg_imgs)
250+
240251
# %%
241252
# Augmentation Transforms
242253
# -----------------------

maintainer_guide.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Torchvision maintainers guide
1+
# Torchvision maintainers guide
22

33
This document aims at documenting user-facing policies / principles used when
44
developing and maintaining torchvision. Other maintainer info (e.g. release

scripts/release_notes/classify_prs.py

+28-46
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,22 @@
11
# In[1]:
2-
3-
# imports and set configuration
42
import pandas as pd
5-
from retrieve_prs_data import run
6-
7-
exclude_prototype = True
8-
data_filename = "10.0_to_11.0-rc2.json"
9-
previous_release = "v10.0"
10-
current_release = "v11.0-rc2"
113

124
# In[2]:
13-
14-
5+
data_filename = "data.json"
156
df = pd.read_json(data_filename).T
167
df.tail()
178

18-
199
# In[3]:
20-
21-
2210
all_labels = {lbl for labels in df["labels"] for lbl in labels}
2311
all_labels
2412

25-
2613
# In[4]:
27-
28-
2914
# Add one column per label
3015
for label in all_labels:
3116
df[label] = df["labels"].apply(lambda labels_list: label in labels_list)
3217
df.head()
3318

34-
3519
# In[5]:
36-
37-
3820
# Add a clean "module" column. It contains tuples since PRs can have more than one module.
3921
# Maybe we should include "topics" in that column as well?
4022

@@ -51,37 +33,26 @@
5133
df["module"] = df.module.apply(tuple)
5234
df.head()
5335

54-
5536
# In[6]:
56-
57-
5837
mod_df = df.set_index("module").sort_index()
5938
mod_df.tail()
6039

61-
6240
# In[7]:
63-
64-
6541
# All improvement PRs
6642
mod_df[mod_df["enhancement"]].head()
6743

68-
6944
# In[8]:
70-
71-
7245
# improvement f module
7346
# note: don't filter module name on the index as the index contain tuples with non-exclusive values
7447
# Use the boolean column instead
7548
mod_df[mod_df["enhancement"] & mod_df["module: transforms"]]
7649

7750

7851
# In[9]:
79-
80-
81-
def format_prs(mod_df):
52+
def format_prs(mod_df, exclude_prototype=True):
8253
out = []
8354
for idx, row in mod_df.iterrows():
84-
if exclude_prototype and row["prototype"]:
55+
if exclude_prototype and "prototype" in row and row["prototype"]:
8556
continue
8657
modules = idx
8758
# Put "documentation" and "tests" first for sorting to be dece
@@ -98,8 +69,6 @@ def format_prs(mod_df):
9869

9970

10071
# In[10]:
101-
102-
10372
included_prs = pd.DataFrame()
10473

10574
# If labels are accurate, this shouhld generate most of the release notes already
@@ -112,27 +81,40 @@ def format_prs(mod_df):
11281
("Bug Fixes", "bug"),
11382
("Code Quality", "code quality"),
11483
):
115-
print(f"## {section_title}")
116-
print()
117-
tmp_df = mod_df[mod_df[module_idx]]
118-
included_prs = pd.concat([included_prs, tmp_df])
119-
print(format_prs(tmp_df))
120-
print()
84+
if module_idx in mod_df:
85+
print(f"## {section_title}")
86+
print()
87+
tmp_df = mod_df[mod_df[module_idx]]
88+
included_prs = pd.concat([included_prs, tmp_df])
89+
print(format_prs(tmp_df))
90+
print()
12191

12292

12393
# In[11]:
124-
125-
12694
# Missing PRs are these ones... classify them manually
12795
missing_prs = pd.concat([mod_df, included_prs]).drop_duplicates(subset="pr_number", keep=False)
12896
print(format_prs(missing_prs))
12997

13098
# In[12]:
131-
13299
# Generate list of contributors
133100
print()
134101
print("## Contributors")
135102

136-
command_to_run = f"{{ git shortlog -s {previous_release}..{current_release} | cut -f2- & git log -s {previous_release}..{current_release} | grep Co-authored | cut -f2- -d: | cut -f1 -d\\< | sed 's/^ *//;s/ *$//' ; }} | sort --ignore-case | uniq | tr '\\n' ';' | sed 's/;/, /g;s/, $//' | fold -s"
137-
rc, output, err = run(command_to_run)
138-
print(output)
103+
previous_release = "c35d3855ccbfa6a36e6ae6337a1f2c721c1f1e78"
104+
current_release = "5181a854d8b127cf465cd22a67c1b5aaf6ccae05"
105+
print(
106+
f"{{ git shortlog -s {previous_release}..{current_release} | cut -f2- & git log -s {previous_release}..{current_release} | grep Co-authored | cut -f2- -d: | cut -f1 -d\\< | sed 's/^ *//;s/ *//' ; }} | sort --ignore-case | uniq | tr '\\n' ';' | sed 's/;/, /g;s/,//' | fold -s"
107+
)
108+
109+
# In[13]:
110+
# Utility to extract PR numbers only from multiple lines, useful to bundle all
111+
# the docs changes for example:
112+
import re
113+
114+
s = """
115+
116+
[] Remove unnecessary dependency from macOS/Conda binaries (#8077)
117+
[rocm] [ROCm] remove HCC references (#8070)
118+
"""
119+
120+
print(", ".join(re.findall("(#\\d+)", s)))

test/test_datasets.py

+26
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,11 @@ def test_transforms_v2_wrapper_spawn(self):
827827
with self.create_dataset(transform=v2.Resize(size=expected_size)) as (dataset, _):
828828
datasets_utils.check_transforms_v2_wrapper_spawn(dataset, expected_size=expected_size)
829829

830+
def test_slice_error(self):
831+
with self.create_dataset() as (dataset, _):
832+
with pytest.raises(ValueError, match="Index must be of type integer"):
833+
dataset[:2]
834+
830835

831836
class CocoCaptionsTestCase(CocoDetectionTestCase):
832837
DATASET_CLASS = datasets.CocoCaptions
@@ -1620,6 +1625,10 @@ def inject_fake_data(self, tmpdir, config):
16201625
num_examples_total += num_examples
16211626
classes.append(cls)
16221627

1628+
if config.pop("make_empty_class", False):
1629+
os.makedirs(pathlib.Path(tmpdir) / "empty_class")
1630+
classes.append("empty_class")
1631+
16231632
return dict(num_examples=num_examples_total, classes=classes)
16241633

16251634
def _file_name_fn(self, cls, ext, idx):
@@ -1644,6 +1653,23 @@ def test_classes(self, config):
16441653
assert len(dataset.classes) == len(info["classes"])
16451654
assert all([a == b for a, b in zip(dataset.classes, info["classes"])])
16461655

1656+
def test_allow_empty(self):
1657+
config = {
1658+
"extensions": self._EXTENSIONS,
1659+
"make_empty_class": True,
1660+
}
1661+
1662+
config["allow_empty"] = True
1663+
with self.create_dataset(config) as (dataset, info):
1664+
assert "empty_class" in dataset.classes
1665+
assert len(dataset.classes) == len(info["classes"])
1666+
assert all([a == b for a, b in zip(dataset.classes, info["classes"])])
1667+
1668+
config["allow_empty"] = False
1669+
with pytest.raises(FileNotFoundError, match="Found no valid file"):
1670+
with self.create_dataset(config) as (dataset, info):
1671+
pass
1672+
16471673

16481674
class ImageFolderTestCase(datasets_utils.ImageDatasetTestCase):
16491675
DATASET_CLASS = datasets.ImageFolder

test/test_datasets_download.py

+5-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import contextlib
22
import itertools
3+
import shutil
34
import tempfile
45
import time
56
import traceback
67
import unittest.mock
78
import warnings
89
from datetime import datetime
9-
from distutils import dir_util
1010
from os import path
1111
from urllib.error import HTTPError, URLError
1212
from urllib.parse import urlparse
@@ -180,7 +180,7 @@ def collect_urls(dataset_cls, *args, **kwargs):
180180
@pytest.fixture(scope="module", autouse=True)
181181
def root():
182182
yield ROOT
183-
dir_util.remove_tree(ROOT)
183+
shutil.rmtree(ROOT)
184184

185185

186186
def places365():
@@ -327,12 +327,6 @@ def kitti():
327327
)
328328

329329

330-
def stanford_cars():
331-
return itertools.chain.from_iterable(
332-
[collect_urls(datasets.StanfordCars, ROOT, split=split, download=True) for split in ["train", "test"]]
333-
)
334-
335-
336330
def url_parametrization(*dataset_urls_and_ids_fns):
337331
return pytest.mark.parametrize(
338332
"url",
@@ -378,9 +372,9 @@ def test_url_is_accessible(url):
378372
retry(lambda: assert_url_is_accessible(url))
379373

380374

381-
@url_parametrization(
382-
stanford_cars, # https://github.com/pytorch/vision/issues/7545
383-
)
375+
# TODO: if e.g. caltech101 starts failing, remove the pytest.mark.parametrize below and use
376+
# @url_parametrization(caltech101)
377+
@pytest.mark.parametrize("url", ("http://url_that_doesnt_exist.com",)) # here until we actually have a failing dataset
384378
@pytest.mark.xfail
385379
def test_url_is_not_accessible(url):
386380
"""

0 commit comments

Comments
 (0)