Commit 47800d49 authored by Sasank Chilamkurthy's avatar Sasank Chilamkurthy
Browse files

Merge branch 'master' of github.com:pytorch/vision

parents 4d7f70b5 ad1dac49
......@@ -280,7 +280,7 @@ to be atleast 224.
The images have to be loaded in to a range of [0, 1] and then
normalized using `mean=[0.485, 0.456, 0.406]` and `std=[0.229, 0.224, 0.225]`
An example of such normalization can be found in `the imagenet example here` <https://github.com/pytorch/examples/blob/42e5b996718797e45c46a25c55b031e6768f8440/imagenet/main.py#L89-L101>
An example of such normalization can be found in the imagenet example `here <https://github.com/pytorch/examples/blob/42e5b996718797e45c46a25c55b031e6768f8440/imagenet/main.py#L89-L101>`__
Transforms
==========
......@@ -410,7 +410,7 @@ computing the ``(min, max)`` over all images.
``pad_value=<float>`` sets the value for the padded pixels.
`Example usage is given in this notebook` <https://gist.github.com/anonymous/bf16430f7750c023141c562f3e9f2a91>
Example usage is given in this `notebook <https://gist.github.com/anonymous/bf16430f7750c023141c562f3e9f2a91>`__
``save_image(tensor, filename, nrow=8, padding=2, normalize=False, range=None, scale_each=False, pad_value=0)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -11,7 +11,7 @@ VERSION = '0.1.9'
requirements = [
'numpy',
'pillow',
'pillow >= 4.1.1',
'six',
'torch',
]
......
......@@ -86,7 +86,7 @@ class Tester(unittest.TestCase):
owidth = random.randint(5, 12) * 2
result = transforms.Compose([
transforms.ToPILImage(),
transforms.Scale((owidth, oheight)),
transforms.Scale((oheight, owidth)),
transforms.ToTensor(),
])(img)
assert result.size(1) == oheight
......@@ -94,7 +94,7 @@ class Tester(unittest.TestCase):
result = transforms.Compose([
transforms.ToPILImage(),
transforms.Scale([owidth, oheight]),
transforms.Scale([oheight, owidth]),
transforms.ToTensor(),
])(img)
assert result.size(1) == oheight
......@@ -150,7 +150,7 @@ class Tester(unittest.TestCase):
assert output.size[0] == width + padding[0] + padding[2]
assert output.size[1] == height + padding[1] + padding[3]
def test_pad_raises_with_invalide_pad_sequence_len(self):
def test_pad_raises_with_invalid_pad_sequence_len(self):
with self.assertRaises(ValueError):
transforms.Pad(())
......@@ -264,6 +264,22 @@ class Tester(unittest.TestCase):
assert np.allclose(img_data_short.numpy(), to_tensor(img_short).numpy())
assert np.allclose(img_data_int.numpy(), to_tensor(img_int).numpy())
def test_tensor_rgba_to_pil_image(self):
trans = transforms.ToPILImage()
to_tensor = transforms.ToTensor()
img_data = torch.Tensor(4, 4, 4).uniform_()
img = trans(img_data)
assert img.mode == 'RGBA'
assert img.getbands() == ('R', 'G', 'B', 'A')
r, g, b, a = img.split()
expected_output = img_data.mul(255).int().float().div(255)
assert np.allclose(expected_output[0].numpy(), to_tensor(r).numpy())
assert np.allclose(expected_output[1].numpy(), to_tensor(g).numpy())
assert np.allclose(expected_output[2].numpy(), to_tensor(b).numpy())
assert np.allclose(expected_output[3].numpy(), to_tensor(a).numpy())
def test_ndarray_to_pil_image(self):
trans = transforms.ToPILImage()
img_data = torch.ByteTensor(4, 4, 3).random_(0, 255).numpy()
......
import torch
import torchvision.utils as utils
import unittest
class Tester(unittest.TestCase):
def test_make_grid_not_inplace(self):
t = torch.rand(5, 3, 10, 10)
t_clone = t.clone()
utils.make_grid(t, normalize=False)
assert torch.equal(t, t_clone), 'make_grid modified tensor in-place'
utils.make_grid(t, normalize=True, scale_each=False)
assert torch.equal(t, t_clone), 'make_grid modified tensor in-place'
utils.make_grid(t, normalize=True, scale_each=True)
assert torch.equal(t, t_clone), 'make_grid modified tensor in-place'
def test_make_grid_raises_with_variable(self):
t = torch.autograd.Variable(torch.rand(3, 10, 10))
with self.assertRaises(TypeError):
utils.make_grid(t)
with self.assertRaises(TypeError):
utils.make_grid([t, t, t, t])
if __name__ == '__main__':
unittest.main()
......@@ -10,7 +10,7 @@ def check_integrity(fpath, md5):
md5o = hashlib.md5()
with open(fpath, 'rb') as f:
# read in 1MB chunks
for chunk in iter(lambda: f.read(1024 * 1024 * 1024), b''):
for chunk in iter(lambda: f.read(1024 * 1024), b''):
md5o.update(chunk)
md5c = md5o.hexdigest()
if md5c != md5:
......
......@@ -8,10 +8,10 @@ __all__ = ['DenseNet', 'densenet121', 'densenet169', 'densenet201', 'densenet161
model_urls = {
'densenet121': 'https://download.pytorch.org/models/densenet121-241335ed.pth',
'densenet169': 'https://download.pytorch.org/models/densenet169-6f0f7f60.pth',
'densenet201': 'https://download.pytorch.org/models/densenet201-4c113574.pth',
'densenet161': 'https://download.pytorch.org/models/densenet161-17b70270.pth',
'densenet121': 'https://download.pytorch.org/models/densenet121-a639ec97.pth',
'densenet169': 'https://download.pytorch.org/models/densenet169-b2777c0a.pth',
'densenet201': 'https://download.pytorch.org/models/densenet201-c1103571.pth',
'densenet161': 'https://download.pytorch.org/models/densenet161-8d451a50.pth',
}
......
......@@ -109,6 +109,9 @@ def to_pil_image(pic):
mode = 'I'
elif npimg.dtype == np.float32:
mode = 'F'
elif npimg.shape[2] == 4:
if npimg.dtype == np.uint8:
mode = 'RGBA'
else:
if npimg.dtype == np.uint8:
mode = 'RGB'
......
......@@ -10,8 +10,8 @@ def make_grid(tensor, nrow=8, padding=2,
Args:
tensor (Tensor or list): 4D mini-batch Tensor of shape (B x C x H x W)
or a list of images all of the same size.
nrow (int, optional): Number of rows in grid. Final grid size is
(B / nrow, nrow). Default is 8.
nrow (int, optional): Number of images displayed in each row of the grid.
The Final grid size is (B / nrow, nrow). Default is 8.
padding (int, optional): amount of padding. Default is 2.
normalize (bool, optional): If True, shift the image to the range (0, 1),
by subtracting the minimum and dividing by the maximum pixel value.
......@@ -26,14 +26,13 @@ def make_grid(tensor, nrow=8, padding=2,
See this notebook `here <https://gist.github.com/anonymous/bf16430f7750c023141c562f3e9f2a91>`_
"""
if not (torch.is_tensor(tensor) or
(isinstance(tensor, list) and all(torch.is_tensor(t) for t in tensor))):
raise TypeError('tensor or list of tensors expected, got {}'.format(type(tensor)))
# if list of tensors, convert to a 4D mini-batch Tensor
if isinstance(tensor, list):
tensorlist = tensor
numImages = len(tensorlist)
size = torch.Size(torch.Size([numImages]) + tensorlist[0].size())
tensor = tensorlist[0].new(size)
for i in irange(numImages):
tensor[i].copy_(tensorlist[i])
tensor = torch.stack(tensor, dim=0)
if tensor.dim() == 2: # single image H x W
tensor = tensor.view(1, tensor.size(0), tensor.size(1))
......@@ -45,6 +44,7 @@ def make_grid(tensor, nrow=8, padding=2,
tensor = torch.cat((tensor, tensor, tensor), 1)
if normalize is True:
tensor = tensor.clone() # avoid modifying tensor in-place
if range is not None:
assert isinstance(range, tuple), \
"range has to be a tuple (min, max) if specified. min and max are numbers"
......@@ -70,14 +70,14 @@ def make_grid(tensor, nrow=8, padding=2,
xmaps = min(nrow, nmaps)
ymaps = int(math.ceil(float(nmaps) / xmaps))
height, width = int(tensor.size(2) + padding), int(tensor.size(3) + padding)
grid = tensor.new(3, height * ymaps + 1 + padding // 2, width * xmaps + 1 + padding // 2).fill_(pad_value)
grid = tensor.new(3, height * ymaps + padding, width * xmaps + padding).fill_(pad_value)
k = 0
for y in irange(ymaps):
for x in irange(xmaps):
if k >= nmaps:
break
grid.narrow(1, y * height + 1 + padding // 2, height - padding)\
.narrow(2, x * width + 1 + padding // 2, width - padding)\
grid.narrow(1, y * height + padding, height - padding)\
.narrow(2, x * width + padding, width - padding)\
.copy_(tensor[k])
k = k + 1
return grid
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment