SerdarHelli commited on
Commit
9d49616
1 Parent(s): a9abdf6

Upload Utils.py

Browse files
Files changed (1) hide show
  1. Utils.py +318 -0
Utils.py ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ @author: serdarhelli
4
+ """
5
+
6
+
7
+ import numpy as np
8
+ import math
9
+ import cv2
10
+ import pydicom
11
+ from pydicom.pixel_data_handlers.util import apply_voi_lut
12
+
13
+
14
+
15
+ def find_center(img):
16
+ thresh=(img)*(255/np.max(img))
17
+ thresh = thresh.astype(np.uint8)
18
+ kernel =( np.ones((5,5), dtype=np.float32))
19
+ ret,thresh = cv2.threshold(thresh, 0, 255, cv2.THRESH_BINARY)
20
+ thresh=cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel,iterations=1 )
21
+ thresh=cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel,iterations=1 )
22
+ thresh=cv2.erode(thresh,kernel,iterations =1)
23
+ contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
24
+ if len(contours)!=0:
25
+ c_area=np.zeros([len(contours)])
26
+ for i in range(len(contours)):
27
+ c_area[i]= cv2.contourArea(contours[i])
28
+ c_1=contours[np.argmax(c_area)]
29
+ M = cv2.moments(c_1)
30
+ cX = int(M["m10"] / M["m00"])
31
+ cY = int(M["m01"] / M["m00"])
32
+ return cX,cY
33
+ else:
34
+ return 0,0
35
+
36
+ def points_center_mass(predict):
37
+ points=np.zeros([6,2])
38
+ for i in range(6):
39
+ points[i,:]=find_center(predict[0,:,:,i])
40
+ return np.int32(points)
41
+
42
+
43
+ def points_max_value(predict):
44
+ points=np.zeros([6,2])
45
+ for i in range(6):
46
+ pre=predict[0,:,:,i]
47
+ points[i,:]=np.where(pre == pre.max())
48
+ return np.fliplr(np.int32(points))
49
+
50
+
51
+ def read_dicom(path, voi_lut = True, fix_monochrome = True):
52
+ dicom = pydicom.read_file(path)
53
+ # VOI LUT (if available by DICOM device) is used to transform raw DICOM data to "human-friendly" view
54
+ if voi_lut:
55
+ data = apply_voi_lut(dicom.pixel_array, dicom)
56
+ else:
57
+ data = dicom.pixel_array
58
+
59
+ # depending on this value, X-ray may look inverted - fix that:
60
+ if fix_monochrome and dicom.PhotometricInterpretation == "MONOCHROME1":
61
+ data = np.amax(data) - data
62
+ # data=data*255
63
+ # data = np.uint8(data)
64
+ try:
65
+ PatientName=str(dicom.PatientName.components[0])
66
+ except:
67
+ PatientName="Empty"
68
+ pass
69
+
70
+ try:
71
+ PatientID=str(dicom.PatientID)
72
+ except:
73
+ PatientID="Empty"
74
+ pass
75
+
76
+ try:
77
+ SOPInstanceUID=str(dicom.SOPInstanceUID.name)
78
+ except:
79
+ SOPInstanceUID="Empty"
80
+ pass
81
+
82
+ try:
83
+ StudyDate=str(dicom.StudyDate)
84
+ except:
85
+ StudyDate="Empty"
86
+ pass
87
+
88
+ try:
89
+ InstitutionAddress=str(dicom.InstitutionName)
90
+ except:
91
+ InstitutionAddress="Empty"
92
+ pass
93
+
94
+ try:
95
+ PatientAge=str(dicom.PatientAge)
96
+ except:
97
+ PatientAge="Empty"
98
+ pass
99
+
100
+ try:
101
+ PatientSex=str(dicom.PatientSex)
102
+ except:
103
+ PatientSex="Empty"
104
+ pass
105
+
106
+ #data -> np.uint16
107
+ return data,PatientName,PatientID,SOPInstanceUID,StudyDate,InstitutionAddress,PatientAge,PatientSex
108
+
109
+
110
+
111
+ def modification_cropping(roi):
112
+ if roi.shape[0]!=roi.shape[1]:
113
+ if roi.shape[0]>roi.shape[1]:
114
+ img2=np.zeros([roi.shape[0],roi.shape[0]])
115
+ add=(roi.shape[0]-roi.shape[1])
116
+ a1=add//2
117
+ a2=add-a1
118
+ img2[:,a1:(roi.shape[0]-a2)]=roi
119
+
120
+ if roi.shape[1]>roi.shape[0]:
121
+ img2=np.zeros([roi.shape[1],roi.shape[1]])
122
+ add=(roi.shape[1]-roi.shape[0])
123
+ a1=add//2
124
+ a2=add-a1
125
+ img2[a1:(roi.shape[1]-a2),:]=roi
126
+ else:
127
+ img2=roi
128
+ return img2
129
+
130
+
131
+ def croping(img,x, y, w, h):
132
+ if y<0:
133
+ y=0
134
+ if abs(w)<abs(h):
135
+ z=np.abs(h-w)
136
+ if img.shape[1]<x+w+(z//2):
137
+ if x-(z//2)>0:
138
+ img2=img[y:y+h, x-(z//2):img.shape[1]].copy()
139
+ else:
140
+ img2=img[y:y+h, 0:img.shape[1]].copy()
141
+ else:
142
+ if x-(z//2)>0:
143
+ img2=img[y:y+h, x-(z//2):x+w+(z//2)].copy()
144
+ else:
145
+ img2=img[y:y+h, 0:x+w+(z//2)].copy()
146
+ if abs(h)<abs(w):
147
+ z=np.abs(h-w)
148
+ if img.shape[0]<y+h+(z//2):
149
+ if y-(z//2)>0:
150
+ img2=img[y-(z//2):img.shape[0], x:x+w].copy()
151
+ else:
152
+ img2=img[0:img.shape[0], x:x+w].copy()
153
+ else:
154
+ if y-(z//2)>0:
155
+ img2=img[y-(z//2):y+h+(z//2), x:x+w].copy()
156
+ else:
157
+ img2=img[0:y+h+(z//2), x:x+w].copy()
158
+ if abs(h)==abs(w):
159
+ img2=img[y:y + h, x:x + w].copy()
160
+ return img2
161
+
162
+
163
+
164
+
165
+
166
+
167
+ def crop_resize(path):
168
+ try:
169
+ data,PatientName,PatientID,SOPInstanceUID,StudyDate,InstitutionAddress,PatientAge,PatientSex=read_dicom(path,False,True)
170
+ except:
171
+ data,PatientName,PatientID,SOPInstanceUID,StudyDate,InstitutionAddress,PatientAge,PatientSex=read_dicom(path,True,True)
172
+ pass
173
+ img = np.copy(data)
174
+
175
+ #Denoise Image
176
+ kernel =( np.ones((5,5), dtype=np.float32))
177
+ img2=cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel,iterations=2 )
178
+ img2=cv2.erode(img2,kernel,iterations =2)
179
+ if len(img2.shape)==3:
180
+ img2=img2[:,:,0]
181
+
182
+ #Threshhold 100- 4096
183
+ ret,thresh = cv2.threshold(img2,100, 4096, cv2.THRESH_BINARY)
184
+
185
+ #To Thresh uint8 becasue "findContours" doesnt accept uint16
186
+ thresh =((thresh/np.max(thresh))*255).astype('uint8')
187
+ a1,b1=thresh.shape
188
+ #Find Countours
189
+ contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
190
+
191
+ #If There is no countour
192
+ if len(contours)==0:
193
+ return thresh,PatientName,PatientID,SOPInstanceUID,StudyDate,InstitutionAddress,PatientAge,PatientSex
194
+
195
+ #Get Areas
196
+ c_area=np.zeros([len(contours)])
197
+ for i in range(len(contours)):
198
+ c_area[i]= cv2.contourArea(contours[i])
199
+
200
+ #Find Max Countour
201
+ cnts=contours[np.argmax(c_area)]
202
+ x, y, w, h = cv2.boundingRect(cnts)
203
+
204
+ #Posibble Square
205
+ roi = croping(data, x, y, w, h)
206
+
207
+ # Absolute Square
208
+ roi=modification_cropping(roi)
209
+
210
+ # Resize to 256x256 with Inter_Nearest
211
+ roi=cv2.resize(roi,(256,256),interpolation=cv2.INTER_NEAREST)
212
+
213
+ return roi,PatientName,PatientID,SOPInstanceUID,StudyDate,InstitutionAddress,PatientAge,PatientSex
214
+
215
+ def put_text_point(original_img,heatpoint):
216
+ original_img =((original_img/np.max(original_img))*255).astype('uint8')
217
+ color = (0, 51, 204)
218
+ img = cv2.cvtColor(original_img, cv2.COLOR_BGR2RGB)
219
+ for i in range(6):
220
+ if heatpoint[i,0]<=0 and heatpoint[i,1]<=0:
221
+ print("L"+str(i)+" There is no Point")
222
+ else :
223
+ if i>2:
224
+ coordx=0
225
+ coordy=-(i*3)
226
+ else:
227
+ coordx=-(i*3)
228
+ coordy=+(i*3)+10
229
+ img=cv2.putText(img, "L"+str(i),(heatpoint[i,0]+coordx,heatpoint[i,1]+coordy), cv2.FONT_HERSHEY_SIMPLEX,0.35, color, 1)
230
+ img = cv2.circle(img, (heatpoint[i,0],heatpoint[i,1]), radius=2, color=color, thickness=-1)
231
+ return img
232
+
233
+ def get_vector(pt1,pt2):
234
+ vec=np.zeros([2])
235
+ vec[1]=(pt2[1]-pt1[1])
236
+ vec[0]=(pt2[0]-pt1[0])
237
+ return vec
238
+
239
+ def dotproduct(v1, v2):
240
+ return sum((a*b) for a, b in zip(v1, v2))
241
+
242
+ def length(v):
243
+ return math.sqrt(dotproduct(v, v))
244
+
245
+ def getAngle(v1, v2):
246
+ if length(v1)==0 or length(v2)==0:
247
+ return "Failed"
248
+ return math.degrees(math.acos(dotproduct(v1, v2) / (length(v1) * length(v2))))
249
+
250
+ def bisector_vector(v1,v2):
251
+ if length(v1)==0 or length(v2) ==0:
252
+ return [0,0]
253
+ v1=v1/(length(v1))
254
+ v2=v2/(length(v2))
255
+ v3=(v1+v2)
256
+ return v3
257
+
258
+
259
+ #magnitude 50 length to l1 to l3
260
+ def angle_patellercongruence(heatpoint,magnitude=50):
261
+ v1=get_vector(heatpoint[1,:],heatpoint[2,:])
262
+ v2=get_vector(heatpoint[1,:],heatpoint[0,:])
263
+ v3=get_vector(heatpoint[1,:],heatpoint[3,:])
264
+ v4=bisector_vector(v1,v2)
265
+ v=np.int32(v4*magnitude)
266
+ coord=v+heatpoint[1,:]
267
+ if length(v3)==0:
268
+ return "Failed",[0,0]
269
+ angle_patellercongruence=getAngle(v3/(length(v3)),v4)
270
+ return angle_patellercongruence,coord
271
+
272
+ def angle_paraleltilt_displacement(heatpoint):
273
+ v1=get_vector(heatpoint[4,:],heatpoint[5,:])
274
+ v2=get_vector(heatpoint[0,:],heatpoint[2,:])
275
+ angle_paraleltilt=getAngle(v1,v2)
276
+ return angle_paraleltilt
277
+
278
+
279
+ def draw_angle(img,heatpoint):
280
+ color = (255, 26, 26)
281
+ color2=(255, 255, 0)
282
+ color3=(51, 255, 51)
283
+ if np.min(heatpoint[0:3,:])<=0:
284
+ patellercongruence,angle_paraleltilt="Failed"
285
+ return img
286
+ if np.min(heatpoint[3:,:])<=0:
287
+ angle_paraleltilt="Failed"
288
+ v1=get_vector(heatpoint[1,:],heatpoint[2,:])
289
+ v2=get_vector(heatpoint[1,:],heatpoint[0,:])
290
+ angle=getAngle(v1,v2)
291
+ patellercongruence,coord=angle_patellercongruence(heatpoint)
292
+ angle_paraleltilt=angle_paraleltilt_displacement(heatpoint)
293
+ img=cv2.line(img,tuple( (heatpoint[1,:])), tuple((heatpoint[2,:])), color, thickness=1, lineType=8)
294
+ img=cv2.line(img, tuple((heatpoint[1,:])), tuple((heatpoint[0,:])), color, thickness=1, lineType=8)
295
+ img=cv2.line(img, tuple((heatpoint[1,:])), tuple((heatpoint[3,:])), color2, thickness=1, lineType=8)
296
+ img=cv2.line(img, tuple((heatpoint[4,:])), tuple((heatpoint[5,:])), color3, thickness=1, lineType=8)
297
+ img=cv2.line(img, tuple((heatpoint[0,:])), tuple((heatpoint[2,:])), color3, thickness=1, lineType=8)
298
+ img=cv2.line(img,tuple( (heatpoint[1,:])), tuple(coord), color2, thickness=1, lineType=8)
299
+ img=cv2.putText(img,"Pateller Congruence Angle :"+str(round(patellercongruence,2)),(25,25), cv2.FONT_HERSHEY_SIMPLEX,0.35, color2, 1)
300
+ img=cv2.putText(img,"Paralel Tilt Angle :"+str(round(angle_paraleltilt,2)),(50,50), cv2.FONT_HERSHEY_SIMPLEX,0.35, color3, 1)
301
+ img=cv2.putText(img, "Angle :"+str(round(angle,2)),(heatpoint[1,0]+10,heatpoint[1,1]+15), cv2.FONT_HERSHEY_SIMPLEX,0.35, color,1)
302
+ return img,patellercongruence,angle_paraleltilt
303
+
304
+ def predict(img,model):
305
+ #Normalization
306
+ img=np.float32(img/(np.max(img)))
307
+ img=np.reshape(img,(1,256,256,1))
308
+ predictions=model.predict(img)
309
+ #Get Final Prediction
310
+ pre=predictions[-1]
311
+ return pre
312
+
313
+
314
+
315
+
316
+
317
+
318
+