def test_decode_png(img_path, pil_mode, mode): with Image.open(img_path) as img: if pil_mode is not None: img = img.convert(pil_mode) img_pil = torch.from_numpy(np.array(img)) img_pil = normalize_dimensions(img_pil) if img_path.endswith("16.png"): # 16 bits image decoding is supported, but only as a private API # FIXME: see https://github.com/pytorch/vision/issues/4731 for potential solutions to making it public with pytest.raises(RuntimeError, match="At most 8-bit PNG images are supported"): data = read_file(img_path) img_lpng = decode_image(data, mode=mode) img_lpng = _read_png_16(img_path, mode=mode) assert img_lpng.dtype == torch.int32 # PIL converts 16 bits pngs in uint8 img_lpng = torch.round(img_lpng / (2**16 - 1) * 255).to(torch.uint8) else: data = read_file(img_path) img_lpng = decode_image(data, mode=mode) tol = 0 if pil_mode is None else 1 if PILLOW_VERSION >= (8, 3) and pil_mode == "LA": # Avoid checking the transparency channel until # https://github.com/python-pillow/Pillow/issues/5593#issuecomment-878244910 # is fixed. # TODO: remove once fix is released in PIL. Should be > 8.3.1. img_lpng, img_pil = img_lpng[0], img_pil[0] torch.testing.assert_close(img_lpng, img_pil, atol=tol, rtol=0)
def test_decode_image(self): for img_path in get_images(IMAGE_ROOT, ".jpg"): img_pil = torch.load(img_path.replace('jpg', 'pth')) img_pil = img_pil.permute(2, 0, 1) img_ljpeg = decode_image(read_file(img_path)) self.assertTrue(img_ljpeg.equal(img_pil)) for img_path in get_images(IMAGE_DIR, ".png"): img_pil = torch.from_numpy(np.array(Image.open(img_path))) img_pil = img_pil.permute(2, 0, 1) img_lpng = decode_image(read_file(img_path)) self.assertTrue(img_lpng.equal(img_pil))
def test_decode_jpeg(self): conversion = [(None, 0), ("L", 1), ("RGB", 3)] for img_path in get_images(IMAGE_ROOT, ".jpg"): for pil_mode, channels in conversion: with Image.open(img_path) as img: is_cmyk = img.mode == "CMYK" if pil_mode is not None: if is_cmyk: # libjpeg does not support the conversion continue img = img.convert(pil_mode) img_pil = torch.from_numpy(np.array(img)) if is_cmyk: # flip the colors to match libjpeg img_pil = 255 - img_pil img_pil = normalize_dimensions(img_pil) data = read_file(img_path) img_ljpeg = decode_image(data, channels=channels) # Permit a small variation on pixel values to account for implementation # differences between Pillow and LibJPEG. abs_mean_diff = (img_ljpeg.type(torch.float32) - img_pil).abs().mean().item() self.assertTrue(abs_mean_diff < 2) with self.assertRaisesRegex(RuntimeError, "Expected a non empty 1-dimensional tensor"): decode_jpeg(torch.empty((100, 1), dtype=torch.uint8)) with self.assertRaisesRegex(RuntimeError, "Expected a torch.uint8 tensor"): decode_jpeg(torch.empty((100, ), dtype=torch.float16)) with self.assertRaises(RuntimeError): decode_jpeg(torch.empty((100), dtype=torch.uint8))
def test_decode_jpeg_cuda(mode, img_path, scripted): if "cmyk" in img_path: pytest.xfail("Decoding a CMYK jpeg isn't supported") data = read_file(img_path) img = decode_image(data, mode=mode) f = torch.jit.script(decode_jpeg) if scripted else decode_jpeg img_nvjpeg = f(data, mode=mode, device="cuda") # Some difference expected between jpeg implementations assert (img.float() - img_nvjpeg.cpu().float()).abs().mean() < 2
def test_decode_png(img_path, pil_mode, mode): with Image.open(img_path) as img: if pil_mode is not None: img = img.convert(pil_mode) img_pil = torch.from_numpy(np.array(img)) img_pil = normalize_dimensions(img_pil) data = read_file(img_path) img_lpng = decode_image(data, mode=mode) tol = 0 if pil_mode is None else 1 assert img_lpng.allclose(img_pil, atol=tol)
def test_decode_png(self): conversion = [(None, 0), ("L", 1), ("LA", 2), ("RGB", 3), ("RGBA", 4)] for img_path in get_images(FAKEDATA_DIR, ".png"): for pil_mode, channels in conversion: with Image.open(img_path) as img: if pil_mode is not None: img = img.convert(pil_mode) img_pil = torch.from_numpy(np.array(img)) img_pil = normalize_dimensions(img_pil) data = read_file(img_path) img_lpng = decode_image(data, channels=channels) tol = 0 if conversion is None else 1 self.assertTrue(img_lpng.allclose(img_pil, atol=tol)) with self.assertRaises(RuntimeError): decode_png(torch.empty((), dtype=torch.uint8)) with self.assertRaises(RuntimeError): decode_png(torch.randint(3, 5, (300,), dtype=torch.uint8))
def test_decode_png(img_path, pil_mode, mode): with Image.open(img_path) as img: if pil_mode is not None: img = img.convert(pil_mode) img_pil = torch.from_numpy(np.array(img)) img_pil = normalize_dimensions(img_pil) data = read_file(img_path) img_lpng = decode_image(data, mode=mode) tol = 0 if pil_mode is None else 1 if PILLOW_VERSION >= (8, 3) and pil_mode == "LA": # Avoid checking the transparency channel until # https://github.com/python-pillow/Pillow/issues/5593#issuecomment-878244910 # is fixed. # TODO: remove once fix is released in PIL. Should be > 8.3.1. img_lpng, img_pil = img_lpng[0], img_pil[0] torch.testing.assert_close(img_lpng, img_pil, atol=tol, rtol=0)
def test_decode_jpeg(img_path, pil_mode, mode): with Image.open(img_path) as img: is_cmyk = img.mode == "CMYK" if pil_mode is not None: if is_cmyk: # libjpeg does not support the conversion pytest.xfail("Decoding a CMYK jpeg isn't supported") img = img.convert(pil_mode) img_pil = torch.from_numpy(np.array(img)) if is_cmyk: # flip the colors to match libjpeg img_pil = 255 - img_pil img_pil = normalize_dimensions(img_pil) data = read_file(img_path) img_ljpeg = decode_image(data, mode=mode) # Permit a small variation on pixel values to account for implementation # differences between Pillow and LibJPEG. abs_mean_diff = (img_ljpeg.type(torch.float32) - img_pil).abs().mean().item() assert abs_mean_diff < 2