前面的介紹有提到Dicom有分成單幀(Single-frame)及多幀(multi-frame),單幀的dicom檔要取出圖片非常簡單,不只可以使用java(dcm4che)還能使用python(Pydicom)來完成。但是多幀的dicom檔要取出圖片就困難許多,今天就來用一個簡單的範例來解出multi-frame dicom檔的圖片。這個範例會使用dcm4che(範例使用的版本為5.22.4)和opencv函式庫,以java SpringBoot框架進行開發。
首先需要import一些dependency
<!-- <!– https://mvnrepository.com/artifact/dcm4che/dcm4che –>-->
<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目錄下才能將服務運行起來。
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這個檔案,後續會再介紹將服務容器化的方法。