iT邦幫忙

2024 iThome 鐵人賽

DAY 12
0
Software Development

數位醫療與雲原生第一次的親密接觸系列 第 12

Day 12 [數位醫療] 快速取出Multi-frame Dicom內的圖片

  • 分享至 

  • xImage
  •  

前面的介紹有提到Dicom有分成單幀(Single-frame)及多幀(multi-frame),單幀的dicom檔要取出圖片非常簡單,不只可以使用java(dcm4che)還能使用python(Pydicom)來完成。但是多幀的dicom檔要取出圖片就困難許多,今天就來用一個簡單的範例來解出multi-frame dicom檔的圖片。這個範例會使用dcm4che(範例使用的版本為5.22.4)和opencv函式庫,以java SpringBoot框架進行開發。

首先需要import一些dependency


<!--        &lt;!&ndash; https://mvnrepository.com/artifact/dcm4che/dcm4che &ndash;&gt;-->
      <dependency>
          <groupId>dcm4che</groupId>
          <artifactId>dcm4che</artifactId>
          <version>2.0.29</version>
          <type>pom</type>
      </dependency>

      <!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-core -->
      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-core</artifactId>
          <version>5.22.4</version>
          <exclusions>
              <exclusion>
                  <artifactId>slf4j-log4j12</artifactId>
                  <groupId>org.slf4j</groupId>
              </exclusion>
          </exclusions>
      </dependency>

      <!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-imageio -->
      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-imageio</artifactId>
          <version>5.22.4</version>
      </dependency>

      <!-- https://mvnrepository.com/artifact/org.dcm4che.tool/dcm4che-tool-common -->
      <dependency>
          <groupId>org.dcm4che.tool</groupId>
          <artifactId>dcm4che-tool-common</artifactId>
          <version>5.22.4</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
      <dependency>
          <groupId>commons-cli</groupId>
          <artifactId>commons-cli</artifactId>
          <version>1.4</version>
      </dependency>


      <!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-image -->
      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-image</artifactId>
          <version>5.22.4</version>
          <exclusions>
              <exclusion>
                  <artifactId>slf4j-log4j12</artifactId>
                  <groupId>org.slf4j</groupId>
              </exclusion>
          </exclusions>
      </dependency>

      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-imageio-opencv</artifactId>
          <version>5.22.4</version>
      </dependency>

      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-imageio-rle</artifactId>
          <version>5.22.4</version>
          <scope>runtime</scope>
      </dependency>
>

      <!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-json -->
      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-json</artifactId>
          <version>5.22.4</version>
      </dependency>

dcm4che的dependency有時無法自動import,需要自己上網找並將其下載下來。

另外因為有用到opencv函式庫,如果是開發環境是windows,需要將dcm4che的opencv.dll放在openjdk的bin目錄下才能將服務運行起來。

https://ithelp.ithome.com.tw/upload/images/20240920/201619877Uxs4SbM9b.png

import完必須的dependency後,就可以開始寫程式啦!

這邊會分兩種寫法,一種是讀取本地的檔案後拆分出圖片,另一種則是上傳檔案後拆分出圖片。

讀取本地的檔案後拆分出圖片


/**
     * 讀取本地dicom檔,並將dicom檔轉換為PNG後寫入本機端
     * <p>
     * dicom檔本機端路徑
     *
     * @param dcmPath PNG檔本機端路徑
     * @param imgPath 回傳PNG儲存位置
     * @return
     */
    public String dicomToPng(String dcmPath, String imgPath) {

        File dcmFile = new File(dcmPath);

        DicomInputStream in = null;

        Attributes attr = null;

        try {
            in = new DicomInputStream(new File(dcmPath));

            InputStream ii = null;

            attr = in.readDataset(-1, -1);
        } catch (Exception e) {

        }
        System.out.println("PatientName :" + attr.getString(Tag.PatientName));

        File imgFile = new File(imgPath);

        ImageInputStream iis = null;
        BufferedImage bi;
        OutputStream out = null;

        ImageReader imageReader = ImageIO.getImageReadersByFormatName("DICOM").next();

 
        try {

            iis = ImageIO.createImageInputStream(dcmFile);

            imageReader.setInput(iis, true);

            imageReader.getNumImages(true);

            String formatName = "png";


            if ((imgPath.substring(imgPath.length() - 1).equals("\\"))) {
                System.out.println("有反斜線");
            } else {
                System.out.println("沒有反斜線");

                imgPath += "\\";
            }
           
            for (int x = 0; x < imageReader.getNumImages(true); x++) {
                bi = imageReader.read(x);
                File fff = new File(imgPath + (x + 1) + ".png");
               
                ImageIO.write(bi, formatName, fff);
            }

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Failed Again 555");
        } finally {
            SafeClose.close(iis);
            SafeClose.close(out);
        }
        return "PNG儲存於 : " + imgPath;
    }


上傳檔案後拆分出圖片

 /**
     * 上傳Dicom檔,拆分出圖片後回傳Base64字串
     *
     */
    public String dicomToPngUpload(MultipartFile multipartFile) {

        DicomInputStream in = null;

        String fileName = multipartFile.getOriginalFilename();

        File dcmFile = new File("/usr");

        Attributes attr = null;

        try {

            dcmFile = File.createTempFile(fileName, fileName);

            multipartFile.transferTo(dcmFile);

            in = new DicomInputStream(dcmFile);

            attr = in.readDataset(-1, -1);

            in.readValue();

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

                SafeClose.close(in);
        }

        //取出dicom檔裡的病患資訊
        System.out.println("patient name : " + attr.getString(Tag.PatientName));

        ImageInputStream iis = null;

        BufferedImage bi;

        OutputStream out = null;

        ImageReader imageReader = ImageIO.getImageReadersByFormatName("DICOM").next();

        String png1 = null;

        String base64 = null ;


        try {

            System.out.println("formatname : " + imageReader.getFormatName());

            iis = ImageIO.createImageInputStream(dcmFile);

            imageReader.setInput(iis, true);

            imageReader.getNumImages(true);

//            可以迴圈方式將圖片全部取出 
//            for (int x = 0; x < imageReader.getNumImages(true); x++) {

//                bi = imageReader.read(x);

//              取出第一張圖片
                bi = imageReader.read(0);
            
                ByteArrayOutputStream stream = new ByteArrayOutputStream();

                ImageIO.write(bi, "png", stream);
                base64 = Base64.encode(stream.toByteArray());

                System.out.println(base64);
                png1 = base64;
//                }

                stream.flush();
                stream.close();

//            }

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Failed Again 555");
        } finally {
            SafeClose.close(iis);
            SafeClose.close(out);
        }


        return png1;
    }

以上就是這次從multi-frame Dicom取出圖片的教學了,因為會用到opencv的函式庫,所以在打包成docker image時,需要加入libopencv_java.so這個檔案,後續會再介紹將服務容器化的方法。


上一篇
Day 11 [數位醫療] Dicom介紹
下一篇
Day 13 [數位醫療] 從零開始手搓multi-frame dicom
系列文
數位醫療與雲原生第一次的親密接觸30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言