Repository: Project-MONAI/MONAI

Issue:
Add support to read DICOM series
**Is your feature request related to a problem? Please describe.**
For 3D DICOM image, it can save several 2D images in series, so we need to leverage ITK to read them.



Discussion:

Resolving patch:
diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py
--- a/monai/data/image_reader.py
+++ b/monai/data/image_reader.py
@@ -9,6 +9,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import os
 from abc import ABC, abstractmethod
 from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
 
@@ -125,6 +126,22 @@ def read(self, data: Union[Sequence[str], str], **kwargs):
         kwargs_ = self.kwargs.copy()
         kwargs_.update(kwargs)
         for name in filenames:
+            if os.path.isdir(name):
+                # read DICOM series of 1 image in a folder, refer to: https://github.com/RSIP-Vision/medio
+                names_generator = itk.GDCMSeriesFileNames.New()
+                names_generator.SetUseSeriesDetails(True)
+                names_generator.AddSeriesRestriction("0008|0021")  # Series Date
+                names_generator.SetDirectory(name)
+                series_uid = names_generator.GetSeriesUIDs()
+
+                if len(series_uid) == 0:
+                    raise FileNotFoundError(f"no DICOMs in: {name}.")
+                if len(series_uid) > 1:
+                    raise OSError(f"the directory: {name} contains more than one DICOM series.")
+
+                series_identifier = series_uid[0]
+                name = names_generator.GetFileNames(series_identifier)
+
             img_.append(itk.imread(name, **kwargs_))
         return img_ if len(filenames) > 1 else img_[0]
 


Test patch:
diff --git a/tests/test_load_image.py b/tests/test_load_image.py
--- a/tests/test_load_image.py
+++ b/tests/test_load_image.py
@@ -68,6 +68,12 @@
     (3, 128, 128, 128),
 ]
 
+TEST_CASE_10 = [
+    {"image_only": False, "reader": ITKReader(pixel_type=itk.UC)},
+    "tests/testing_data/CT_DICOM",
+    (4, 16, 16),
+]
+
 
 class TestLoadImage(unittest.TestCase):
     @parameterized.expand([TEST_CASE_1, TEST_CASE_2, TEST_CASE_3, TEST_CASE_4, TEST_CASE_5])
@@ -105,6 +111,24 @@ def test_itk_reader(self, input_param, filenames, expected_shape):
                 np.testing.assert_allclose(header["original_affine"], np.eye(4))
             self.assertTupleEqual(result.shape, expected_shape)
 
+    @parameterized.expand([TEST_CASE_10])
+    def test_itk_dicom_series_reader(self, input_param, filenames, expected_shape):
+        result, header = LoadImage(**input_param)(filenames)
+        self.assertTrue("affine" in header)
+        self.assertEqual(header["filename_or_obj"], filenames)
+        np.testing.assert_allclose(
+            header["affine"],
+            np.array(
+                [
+                    [0.488281, 0.0, 0.0, -125.0],
+                    [0.0, 0.488281, 0.0, -128.100006],
+                    [0.0, 0.0, 68.33333333, -99.480003],
+                    [0.0, 0.0, 0.0, 1.0],
+                ]
+            ),
+        ),
+        self.assertTupleEqual(result.shape, expected_shape)
+
     def test_load_png(self):
         spatial_size = (256, 256)
         test_image = np.random.randint(0, 256, size=spatial_size)
diff --git a/tests/testing_data/CT_DICOM/17106 b/tests/testing_data/CT_DICOM/17106
new file mode 100644
Binary files /dev/null and b/tests/testing_data/CT_DICOM/17106 differ
diff --git a/tests/testing_data/CT_DICOM/17136 b/tests/testing_data/CT_DICOM/17136
new file mode 100644
Binary files /dev/null and b/tests/testing_data/CT_DICOM/17136 differ
diff --git a/tests/testing_data/CT_DICOM/17166 b/tests/testing_data/CT_DICOM/17166
new file mode 100644
Binary files /dev/null and b/tests/testing_data/CT_DICOM/17166 differ
diff --git a/tests/testing_data/CT_DICOM/17196 b/tests/testing_data/CT_DICOM/17196
new file mode 100644
Binary files /dev/null and b/tests/testing_data/CT_DICOM/17196 differ