| 145 | class TestRotated3DXY(NumpyImageTestCase3D): |
| 146 | @parameterized.expand(TEST_CASES_3D) |
| 147 | def test_correct_results(self, im_type, angle, keep_size, mode, padding_mode, align_corners): |
| 148 | rotate_fn = Rotated( |
| 149 | ("img", "seg"), [0, 0, angle], keep_size, (mode, "nearest"), padding_mode, align_corners, dtype=np.float64 |
| 150 | ) |
| 151 | rotated = rotate_fn({"img": im_type(self.imt[0]), "seg": im_type(self.segn[0])}) |
| 152 | if keep_size: |
| 153 | np.testing.assert_allclose(self.imt[0].shape, rotated["img"].shape) |
| 154 | _order = 0 if mode == "nearest" else 1 |
| 155 | if padding_mode == "border": |
| 156 | _mode = "nearest" |
| 157 | elif padding_mode == "reflection": |
| 158 | _mode = "reflect" |
| 159 | else: |
| 160 | _mode = "constant" |
| 161 | expected = scipy.ndimage.rotate( |
| 162 | self.imt[0, 0], -np.rad2deg(angle), (0, 1), not keep_size, order=_order, mode=_mode, prefilter=False |
| 163 | ) |
| 164 | for k, v in rotated.items(): |
| 165 | rotated[k] = v.cpu() if isinstance(v, torch.Tensor) else v |
| 166 | good = np.sum(np.isclose(expected, rotated["img"][0], atol=1e-3)) |
| 167 | self.assertLessEqual(np.abs(good - expected.size), 5, "diff at most 5 voxels") |
| 168 | |
| 169 | expected = scipy.ndimage.rotate( |
| 170 | self.segn[0, 0], -np.rad2deg(angle), (0, 1), not keep_size, order=0, mode=_mode, prefilter=False |
| 171 | ) |
| 172 | expected = np.stack(expected).astype(int) |
| 173 | if isinstance(rotated["seg"], MetaTensor): |
| 174 | rotated["seg"] = rotated["seg"].as_tensor() # pytorch 1.7 compatible |
| 175 | self.assertLessEqual(np.count_nonzero(expected != rotated["seg"][0]), 160) |
| 176 | |
| 177 | |
| 178 | if __name__ == "__main__": |