Organ-aware 3D lesion segmentation dataset and pipeline for abdominal CT analysis (ACM Multimedia 2025 candidate)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SegmentiontoImageData.py 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import numpy as np
  2. import pydicom
  3. import os
  4. import re
  5. import cv2
  6. from natsort import natsorted
  7. import matplotlib.pyplot as plt
  8. class SegmentiontoImageData():
  9. def __init__(self, DICOM_File, predict_File):
  10. self.pixelSpacing = (1,1)
  11. self.initial_position = (1,1,1)
  12. self.DICOM_File_PATH = DICOM_File
  13. self.predict_File_PATH = predict_File
  14. # self.itemColorList_txt = itemColorList_txt
  15. self.pixelDatabase = []
  16. # self.items = []
  17. self.itemsLen = 0
  18. # self.ROIColor = []
  19. self.DICOMInformation = []
  20. self.spacingDatabase = []
  21. self.contourSequence = []
  22. self.imageList = []
  23. self.numberOfImage = 0
  24. def __call__(self):
  25. print('get Contour Sequence from Images.', end='') #從影像獲取輪廓
  26. self.getDICOMinformation()
  27. # self.getItemColor()
  28. self.getImageData()
  29. self.pixeltoSpacing()
  30. return [self.spacingDatabase, self.DICOMInformation]
  31. def getSliceLocation(self, filename):
  32. for i in range(len(self.DICOMInformation)):
  33. # if(self.DICOMInformation[i].SOPInstanceUID == filename):
  34. if(self.DICOMInformation[i].SOPInstanceUID == filename[3:]):
  35. return self.DICOMInformation[i].SliceLocation
  36. return -1
  37. def getDICOMinformation(self):
  38. DICOMdir = os.listdir(self.DICOM_File_PATH)
  39. # DICOMdir.sort()
  40. DICOMdir = natsorted(DICOMdir)
  41. # print(DICOMdir)
  42. for DICOMName in DICOMdir:
  43. filename = self.DICOM_File_PATH + DICOMName
  44. # print(filename)
  45. dataset = pydicom.dcmread(filename)
  46. if(dataset.Modality == "CT"):
  47. self.DICOMInformation.append(dataset)
  48. self.pixelSpacing = self.DICOMInformation[0].PixelSpacing
  49. self.initial_position = self.DICOMInformation[0].ImagePositionPatient
  50. # def getItemColor(self):
  51. # with open(self.itemColorList_txt) as f:
  52. # content = f.read()
  53. # x = re.split(",|:|\[|\]|\*|\n|'",str(content))
  54. # for i in range(0, len(x)-1, 6):
  55. # item = x[i]
  56. # R = int(x[i+2].split('\"')[1])
  57. # G = int(x[i+3].split('\"')[1])
  58. # B = int(x[i+4].split('\"')[1])
  59. # self.items.append(item)
  60. # self.ROIColor.append([item, [B, G, R]])
  61. # def getItemColor(self):
  62. # with open(self.itemColorList_txt) as f:
  63. # content = f.read()
  64. # x = re.split(",|:|\[|\]|\*|\n|'",str(content))
  65. # separation_count = x.count("==========================================")
  66. # if separation_count :
  67. # separation_index = x.index("==========================================")
  68. # x = x[:separation_index]
  69. # for i in range(0, len(x)-1, 8):
  70. # item = x[i]
  71. # R = int(x[i+2].split('\"')[1])
  72. # G = int(x[i+3].split('\"')[1])
  73. # B = int(x[i+4].split('\"')[1])
  74. # self.items.append(item)
  75. # self.ROIColor.append([item, [B, G, R]])
  76. def getImageData(self):
  77. itemsdir = os.listdir(self.predict_File_PATH)
  78. # itemsdir.sort()
  79. itemsdir = natsorted(itemsdir)
  80. # print("----------------------")
  81. # print(itemsdir)
  82. # print("----------------------")
  83. self.itemsLen = len(itemsdir)
  84. for item in itemsdir:
  85. path = self.predict_File_PATH + item
  86. imagesdir = os.listdir(path)
  87. # imagesdir.sort()
  88. imagesdir = natsorted(imagesdir)
  89. # print(len(imagesdir))
  90. self.numberOfImage = len(imagesdir)
  91. pixelData = []
  92. z_axis = -1
  93. for imageName in imagesdir:
  94. name = imageName[:-4]
  95. # name = 'CT.'+imageName[:-4]
  96. # name = imageName[3:-4]
  97. name = name.replace('_OUT', '')
  98. image = cv2.imread(path + "/" + imageName) # 這邊是一張一張讀進來,若是nifti格式可以一次讀再進到這個for迴圈
  99. imgray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  100. ret,thresh = cv2.threshold(imgray,127,255,0)
  101. #plt.imshow(thresh)
  102. #plt.show()
  103. #map = np.zeros((512, 512, 3))
  104. contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
  105. z_axis = z_axis + 1
  106. if(contours == []):
  107. continue
  108. temp = []
  109. for cnt in contours:
  110. cnt = list(np.array(cnt).reshape(-1))
  111. temp.append(cnt)
  112. pixelData.append([name, temp])
  113. #for cnt in contours:
  114. #pixelData.append(cnt)
  115. #cv2.drawContours(map, cnt, -1, (0, 255, 0), -1)
  116. #cv2.imshow("test",map)
  117. #cv2.waitKey(30)
  118. #print(item)
  119. #print(len(pixelData))
  120. self.pixelDatabase.append([item ,pixelData])
  121. def pixeltoSpacing(self):
  122. # organs
  123. for itemNumber in range(self.itemsLen):
  124. item, itemData = self.pixelDatabase[itemNumber]
  125. # print(itemData)
  126. database = []
  127. # organ's images
  128. for imageNumber in range(len(itemData)):
  129. contours = []
  130. name, contoursData = itemData[imageNumber]
  131. z_axis = self.getSliceLocation(name)
  132. # image's contour
  133. for numberOfContour in range(len(contoursData)):
  134. coordinate = []
  135. pixelData = contoursData[numberOfContour]
  136. # contour to real world coordinate
  137. for i in range(0, len(pixelData), 2):
  138. x = pixelData[i]
  139. y = pixelData[i+1]
  140. xx = x * self.pixelSpacing[0] + self.initial_position[0]
  141. yy = y * self.pixelSpacing[1] + self.initial_position[1]
  142. zz = z_axis
  143. coordinate.append([xx, yy, zz])
  144. # print(coordinate)
  145. contours.append(coordinate)
  146. if item=='AIBODY':
  147. if len(contours)>1:
  148. for i in contours:
  149. if len(i)>300:
  150. BODY_filter = [i]
  151. contours = BODY_filter
  152. # with open('neckBody.txt', 'a') as f:
  153. # for point in contours[0]:
  154. # print(point, file=f)
  155. database.append(contours)
  156. self.spacingDatabase.append([item, database])
  157. # print(len(self.spacingDatabase)) # 將label以點的形式寫入