def save(self, window, data): name, ok = self.gui.getInputName(window) if ok and name: name = str(name) data.setName(name) dir = './Data/' + name db.saveRawData(dir, self.gui.dataModel, window.index) return True
def load(self, k, i): dataset = {'result': [], 'fix': []} data, info, point = db.loadMatData(self.savepath + self.dirs[k] + self.ini.file.name_result[i] + self.type[k], None) dataset['result'] = db.BasicData(data, info, point) data, info, point = db.loadMatData(self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_fix[i] + '.mat', None) dataset['fix'] = db.BasicData(data, info, point) print 'Data %s loaded!' % self.ini.file.name_result[i] return dataset
def load(self, i): dataset = {'mov': [], 'fix': [], 'seg': []} data, info, point = db.loadMatData(self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_fix[i] + '.mat', None) fileData = db.BasicData(data, info, point) dataset['fix'] = fileData data, info, point = db.loadMatData(self.savepath + self.ini.file.name_result[i] + '_mr.mat', None) fileData = db.BasicData(data, info, point) dataset['seg'] = fileData print 'Data %s loaded!' % self.ini.file.name_result[i] return dataset
def load(self, i): dataset = {'mov': [], 'fix': []} data, info, point = db.loadMatData(self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_mov[i] + '.mat', None) point['Centerline'] = calCenterlineFromContour(point) dataset['mov'] = db.BasicData(data, info, point) data, info, point = db.loadMatData(self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_fix[i] + '.mat', None) point['Centerline'] = calCenterlineFromContour(point) dataset['fix'] = db.BasicData(data, info, point) print 'Data %s loaded!' % self.ini.file.name_result[i] return dataset
def load(self, i): dataset = {'us': [], 'mr': []} data, info, point = db.loadMatData(self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_fix[i] + '.mat', None) fileData = db.BasicData(data, info, point) dataset['mr'] = fileData data, info, point = db.loadMatData(self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_mov[i] + '.mat', None) fileData = db.BasicData(data, info, point) dataset['us'] = fileData print 'Data %s loaded!' % self.ini.file.name_result[i] return dataset
def load(self, i): dataset = {'result': [], 'fix': [], 'mov': []} data, info, point = db.loadMatData(self.path + self.ini.file.datadir + self.ini.file.name_result[i] + '_icp_cen.mat', None) dataset['result'] = db.BasicData(data, info, point) data, info, point = db.loadMatData(self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_fix[i] + '.mat', None) dataset['fix'] = db.BasicData(data, info, point) data, info, point = db.loadMatData(self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_mov[i] + '.mat', None) dataset['mov'] = db.BasicData(data, info, point) print 'Data %s loaded!' % self.ini.file.name_result[i] return dataset
def loadDicomInfo(self, dir, dimension): # Only available for special data (Need to modify for more universal usage) info = db.ImageInfo() data = dicom.read_file(dir) modality = data.Modality info.addData('modality', modality) if modality == 'MR' or modality == 'CT': ps = data.PixelSpacing if modality == 'MR': z = data.SpacingBetweenSlices else: z = data.SliceThickness if dimension == 3: resolution = [float(z), float(ps[0]), float(ps[1])] else: resolution = [float(ps[0]), float(ps[1])] resolution = npy.array(resolution) info.addData('resolution', resolution) orientation = npy.array(map(float, data.ImageOrientationPatient)) info.addData('orientation', orientation) elif modality == 'US': r = data[0x200d, 0x3303].value resolution = npy.array([float(r[2]), float(r[1]), float(r[0])]) info.addData('resolution', resolution) orientation = npy.array(map(float, data[0x200d, 0x3d00].value[0][0x0020, 0x9116].value[0][0x200d, 0x3d16].value)) info.addData('orientation', orientation) # To make the orientation of images compatible view, flip = db.getViewAndFlipFromOrientation(orientation, resolution.shape[0]) info.addData('view', view) info.addData('flip', flip) return info
def load(self, i): dataset = {'mov': [], 'fix': []} data, info, point = db.loadMatData( self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_fix[i] + '.mat', None) fileData = db.BasicData(data, info, point) dataset['fix'] = fileData data, info, point = db.loadMatData( self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_mov[i] + '.mat', None) fileData = db.BasicData(data, info, point) dataset['mov'] = fileData print 'Data %s loaded!' % self.ini.file.name_result[i] return dataset
def process(self, dataset, i): # ICP with centerline print 'Register Data %s with ICP(centerline)...' % self.ini.file.name_result[i] for delta in range(-15, 16): data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1, False, delta) # CLICP #data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 0, False, delta) #SICP #data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1, False, delta, op = True) #CICP #data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 0, False, delta, op = True) #SLICP resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Delta %dmm Done!' % delta mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis(resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole self.error[delta + 15, 0] += mean_whole self.error[delta + 15, 1] += mean_whole ** 2 del data, point, resultData
def process(self, dataset, i): # ICP with centerline print 'Register Data %s with ICP(centerline)...' % self.ini.file.name_result[i] for i in self.dis: for j in self.dis: data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1, down_fix = i, down_mov = j, MaxRate = 1.0) # CLICP #data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 0, False, delta) #SICP #data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1, False, delta, op = True) #CICP #data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 0, False, delta, op = True) #SLICP resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Sample (%d, %d) Done!' % (i, j) mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis(resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole self.error[i - 1, j - 1] += mean_whole del data, point, resultData
def run(self, *args, **kwargs): indexes = self.gui.getRegisterDataIndex() if indexes: if len(indexes) == 2: data, point, para = self.register( self.gui.dataModel[indexes[0]], self.gui.dataModel[indexes[1]]) if data is None: return resultData = db.ResultData( data, db.ImageInfo(self.gui.dataModel[indexes[0]].info.data), point) resultData.addDetail('fix', indexes[0]) resultData.addDetail('move', indexes[1]) resultData.addDetail('transform', para) resultData.setName(None) return resultData
def process(self, dataset, i): ''' mean_dis, mean_whole, max_dis, max_whole = self.contourerror.analysis(dataset['seg'], dataset['fix'].getPointSet('Contour').copy()) print 'Segmentation Contour Error Done! Whole mean is %0.2fmm.' % mean_whole self.sheet1.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet1.write(j + 1, i + 2, mean_dis[j]) self.sheet1.write(4, i + 2, mean_whole) self.book.save(self.path + self.ini.file.savedir + 'Test_segmentation.xls') ''' # ICP with centerline print 'Register Data %s with ICP(centerline)...' % self.ini.file.name_result[ i] data, point, para = self.icp.register(dataset['seg'], dataset['mov'], 1) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getResolution().tolist()) #mean_dis, mean_whole, max_dis, max_whole = self.contourerror.analysis(resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole #dice_index, dice_index_all = self.areaerror.analysis(resultData, dataset['fix'].getPointSet('Contour').copy()) #print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet2.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet2.write(j + 1, i + 2, mean_dis[j]) self.sheet2.write(j + 5, i + 2, max_dis[j]) #self.sheet2.write(j + 9, i + 2, dice_index[j]) self.sheet2.write(4, i + 2, mean_whole) self.sheet2.write(8, i + 2, max_whole) #self.sheet2.write(12, i + 2, dice_index_all) self.book.save(self.path + self.ini.file.savedir + 'Test_segmentation_surface.xls') del data, point, resultData
def process(self, dataset, i): point_us = dataset['us'].pointSet.data['Contour'] point_us = point_us[point_us[:, 0] >= 0][:, 2] point_mr = dataset['mr'].pointSet.data['Contour'] point_mr = point_mr[point_mr[:, 0] >= 0][:, 2] bottom_us = npy.min(point_us) top_us = npy.max(point_us) bif_us = db.getBifurcation(dataset['us'].pointSet.data['Contour']) res_us = dataset['us'].getResolution() bottom_mr = npy.min(point_mr) top_mr = npy.max(point_mr) bif_mr = db.getBifurcation(dataset['mr'].pointSet.data['Contour']) res_mr = dataset['mr'].getResolution() point_mr = dataset['mr'].pointSet.data['Contour'] self.mr[0] += bif_mr - bottom_mr + 1 self.mr[1] += npy.max( point_mr[npy.round(point_mr[:, -1]) == 1][:, 2]) - bif_mr + 1 self.mr[2] += npy.max( point_mr[npy.round(point_mr[:, -1]) == 2][:, 2]) - bif_mr + 1 self.usslices += top_us - bottom_us + 1 self.uspoints += point_us.shape[0] self.mrslices += top_mr - bottom_mr + 1 self.mrpoints += point_mr.shape[0] self.sheet_us.write(i + 1, 0, self.ini.file.name_result[i]) self.sheet_us.write(i + 1, 1, bottom_us) self.sheet_us.write(i + 1, 2, bif_us) self.sheet_us.write(i + 1, 3, top_us) for j in range(3): self.sheet_us.write(i + 1, j + 4, res_us[j]) self.sheet_mr.write(i + 1, 0, self.ini.file.name_result[i]) self.sheet_mr.write(i + 1, 1, bottom_mr) self.sheet_mr.write(i + 1, 2, bif_mr) self.sheet_mr.write(i + 1, 3, top_mr) for j in range(3): self.sheet_mr.write(i + 1, j + 4, res_mr[j]) self.book.save('./Result/count.xls')
def load(self, dir): result = [] for name in dir: data, info, point = db.loadMatData(name, self.gui.dataModel) if info.getData('fix') is not None: fileData = db.ResultData(data, info, point) else: fileData = db.BasicData(data, info, point) result.append(fileData) return result
def getInfo(self, res=[1.0, 1.0, 1.0], ori=0): info = db.ImageInfo() info.addData('modality', 'MR') resolution = npy.array(res) info.addData('resolution', resolution) if ori == 0: # z orientation = npy.array([1, 0, 0, 0, 1, 0]) elif ori == 1: # y orientation = npy.array([1, 0, 0, 0, 0, -1]) elif ori == 2: # x orientation = npy.array([0, 1, 0, 0, 0, -1]) info.addData('orientation', orientation) view, flip = db.getViewAndFlipFromOrientation(orientation, resolution.shape[0]) info.addData('view', view) info.addData('flip', flip) return info
def register(self, fixedData, movingData, discard = False): fixed_points = fixedData.getPointSet('Contour') moving_points = movingData.getPointSet('Contour') fixed_res = fixedData.getResolution().tolist() moving_res = movingData.getResolution().tolist() fixed_points = fixed_points.copy()[npy.where(fixed_points[:, 0] >= 0)] moving_points = moving_points.copy()[npy.where(moving_points[:, 0] >= 0)] # Use the bifurcation as the initial position fixed_bif = db.getBifurcation(fixed_points) moving_bif = db.getBifurcation(moving_points) if (fixed_bif < 0) or (moving_bif < 0): fixed_min = 0 else: temp = moving_points[:, 2:] moving_delta = moving_bif - npy.min(temp[npy.where(npy.round(temp[:, 1]) == 0), 0]) fixed_min = fixed_bif - moving_delta * moving_res[-1] / fixed_res[-1] # Get the result transformation parameters0 T = ml.mat([0, 0, 0]).T; R = ml.mat([[1, 0, 0], [0, 1, 0], [0, 0, 1]]).I; if (fixed_bif >= 0) and (moving_bif >= 0): T[2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) moving_points = movingData.getPointSet('Contour').copy() moving_center = movingData.getPointSet('Centerline').copy() new_trans_points, result_center_points = util.resliceTheResultPoints(moving_points, moving_center, 20, moving_res, fixed_res, discard, R, T) T = -T T = R * T transform = sitk.Transform(3, sitk.sitkAffine) para = R.reshape(1, -1).tolist()[0] + T.T.tolist()[0] transform.SetParameters(para) movingImage = movingData.getSimpleITKImage() fixedImage = fixedData.getSimpleITKImage() resultImage = sitk.Resample(movingImage, fixedImage, transform, sitk.sitkLinear, 0, sitk.sitkFloat32) return sitk.GetArrayFromImage(resultImage), {'Contour': trans_points, 'Centerline': result_center_points}, para + [0, 0, 0]
def process(self, dataset, i): point_us = dataset['us'].pointSet.data['Contour'] point_us = point_us[point_us[:, 0] >= 0][:, 2] point_mr = dataset['mr'].pointSet.data['Contour'] point_mr = point_mr[point_mr[:, 0] >= 0][:, 2] bottom_us = npy.min(point_us) top_us = npy.max(point_us) bif_us = db.getBifurcation(dataset['us'].pointSet.data['Contour']) res_us = dataset['us'].getResolution() bottom_mr = npy.min(point_mr) top_mr = npy.max(point_mr) bif_mr = db.getBifurcation(dataset['mr'].pointSet.data['Contour']) res_mr = dataset['mr'].getResolution() point_mr = dataset['mr'].pointSet.data['Contour'] self.mr[0] += bif_mr - bottom_mr + 1 self.mr[1] += npy.max(point_mr[npy.round(point_mr[:, -1]) == 1][:, 2]) - bif_mr + 1 self.mr[2] += npy.max(point_mr[npy.round(point_mr[:, -1]) == 2][:, 2]) - bif_mr + 1 self.usslices += top_us - bottom_us + 1 self.uspoints += point_us.shape[0] self.mrslices += top_mr - bottom_mr + 1 self.mrpoints += point_mr.shape[0] self.sheet_us.write(i + 1, 0, self.ini.file.name_result[i]) self.sheet_us.write(i + 1, 1, bottom_us) self.sheet_us.write(i + 1, 2, bif_us) self.sheet_us.write(i + 1, 3, top_us) for j in range(3): self.sheet_us.write(i + 1, j + 4, res_us[j]) self.sheet_mr.write(i + 1, 0, self.ini.file.name_result[i]) self.sheet_mr.write(i + 1, 1, bottom_mr) self.sheet_mr.write(i + 1, 2, bif_mr) self.sheet_mr.write(i + 1, 3, top_mr) for j in range(3): self.sheet_mr.write(i + 1, j + 4, res_mr[j]) self.book.save('./Result/count.xls')
def process(self, dataset, i): # ICP with centerline print 'Register Data %s with ICP(centerline)...' % self.ini.file.name_result[ i] for fov in range(7): data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1, False, 0, 9999.0, 1, fov + 1) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'FOV %dmm Done!' % (fov + 1) mean_dis, mean_whole, max_dis, max_whole = self.contourerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole self.error[fov, :3] += mean_dis self.error[fov, 3] += mean_whole del data, point, resultData
def loadDicomInfo(self, dir, dimension): # Only available for special data (Need to modify for more universal usage) info = db.ImageInfo() data = dicom.read_file(dir) modality = data.Modality info.addData('modality', modality) if modality == 'MR' or modality == 'CT': ps = data.PixelSpacing if modality == 'MR': z = data.SpacingBetweenSlices else: z = data.SliceThickness if dimension == 3: resolution = [float(z), float(ps[0]), float(ps[1])] else: resolution = [float(ps[0]), float(ps[1])] resolution = npy.array(resolution) info.addData('resolution', resolution) orientation = npy.array(map(float, data.ImageOrientationPatient)) info.addData('orientation', orientation) elif modality == 'US': r = data[0x200d, 0x3303].value resolution = npy.array([float(r[2]), float(r[1]), float(r[0])]) info.addData('resolution', resolution) orientation = npy.array( map( float, data[0x200d, 0x3d00].value[0][0x0020, 0x9116].value[0][0x200d, 0x3d16].value)) info.addData('orientation', orientation) # To make the orientation of images compatible view, flip = db.getViewAndFlipFromOrientation(orientation, resolution.shape[0]) info.addData('view', view) info.addData('flip', flip) return info
def process(self, dataset, i): print 'Register Data %s with ICP(centerline) with label...' % self.ini.file.name_result[ i] data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' print 'Evaluation Data %s...' % self.ini.file.name_result[i] mean_dis, mean_whole, max_dis, max_whole, result = self.contourerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), True) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole print result for cnt in range(3): for x in result[cnt].keys(): self.result[cnt][x] = self.result[cnt].get(x, 0) + result[cnt][x] self.resultCnt[cnt][x] = self.resultCnt[cnt].get(x, 0) + 1
def load(self, dir): try: data = db.loadDicomArray(dir) except Exception: if self.gui: self.gui.showErrorMessage( "Memory error", "Data exceeded memory limit! If this problem occurs again, please restart the application." ) else: print "Data exceeded memory limit!" return [] # Format: z * x * y if type(data) == tuple: data = npy.concatenate((data[0], data[1]), axis=0) if data.shape[0] == 1: data = data.reshape(data.shape[1:]) info = self.loadDicomInfo(dir[0], len(data.shape)) fileData = db.BasicData(data=data, info=info) return [fileData]
def getInfo(self, res = [1.0, 1.0, 1.0], ori = 0): info = db.ImageInfo() info.addData('modality', 'MR') resolution = npy.array(res) info.addData('resolution', resolution) if ori == 0: # z orientation = npy.array([1, 0, 0, 0, 1, 0]) elif ori == 1: # y orientation = npy.array([1, 0, 0, 0, 0, -1]) elif ori == 2: # x orientation = npy.array([0, 1, 0, 0, 0, -1]) info.addData('orientation', orientation) view, flip = db.getViewAndFlipFromOrientation(orientation, resolution.shape[0]) info.addData('view', view) info.addData('flip', flip) return info
def load(self, dir): try: data = db.loadDicomArray(dir) except Exception: if self.gui: self.gui.showErrorMessage("Memory error", "Data exceeded memory limit! If this problem occurs again, please restart the application.") else: print "Data exceeded memory limit!" return [] # Format: z * x * y if type(data) == tuple: data = npy.concatenate((data[0], data[1]), axis = 0) if data.shape[0] == 1: data = data.reshape(data.shape[1:]) info = self.loadDicomInfo(dir[0], len(data.shape)) fileData = db.BasicData(data = data, info = info) return [fileData]
def KeyPressCallback(self, obj, event): ch = self.parent.window_interactor.GetKeySym() if ch == 'Return': if (self.X1, self.Y1) == (self.X2, self.Y2): return point = npy.round(self.getAllPoint()) if self.parent.dimension: max = npy.max(point, axis = 0) min = npy.min(point, axis = 0) bound = [(min[i], max[i] + 1) for i in range(2)] bound = bound[::-1] else: point[0, self.parent.view] = 0 point[1, self.parent.view] = self.parent.parent.getData().getData().shape[0] - 1 max = npy.max(point, axis = 0) min = npy.min(point, axis = 0) bound = [(min[i], max[i] + 1) for i in range(3)] bound = bound[::-1] info = db.ImageInfo(self.parent.parent.getData().getInfo().data) info.setName(None) if not self.parent.dimension: orientation = npy.array([1, 0, 0, 0, 1, 0]) info.addData('orientation', orientation) resolution = self.parent.parent.getData().getResolution()[::-1] info.addData('resolution', resolution) view, flip = db.getViewAndFlipFromOrientation(orientation, resolution.shape[0]) info.addData('view', view) info.addData('flip', flip) info.addData('clip', npy.array([bound[0][0], bound[0][1], bound[1][0], bound[1][1], bound[2][0], bound[2][1]])) data = db.BasicData(data = self.parent.parent.getData().getData()[bound[0][0]:bound[0][1], bound[1][0]:bound[1][1], bound[2][0]:bound[2][1]], info = info) else: info.addData('clip', npy.array([bound[0][0], bound[0][1], bound[1][0], bound[1][1]])) data = db.BasicData(data = self.parent.parent.getData().getData()[bound[0][0]:bound[0][1], bound[1][0]:bound[1][1]], info = info) self.parent.parent.gui.addNewDataView(data)
def load(self, i): dataset = {'mov': [], 'fix': [], 'seg': []} data, info, point = db.loadMatData( self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_fix[i] + '.mat', None) point['Centerline'] = calCenterlineFromContour(point) fileData = db.BasicData(data, info, point) dataset['fix'] = fileData data, info, point = db.loadMatData( self.path + self.ini.file.datadir + '/Contour/' + self.ini.file.name_mov[i] + '.mat', None) point['Centerline'] = calCenterlineFromContour(point) fileData = db.BasicData(data, info, point) dataset['mov'] = fileData data, info, point = db.loadMatData( self.savepath + self.ini.file.name_result[i] + '_mr.mat', None) fileData = db.BasicData(data, info, point) dataset['seg'] = fileData print 'Data %s loaded!' % self.ini.file.name_result[i] return dataset
def register(self, fixedData, movingData, discard=False): index = self.gui.getDataIndex({ 'Contour': 0, 'Centerline': 1 }, 'Select the object') if index is None: return None, None, None if index == 0: fixed_points = fixedData.getPointSet('Contour') moving_points = movingData.getPointSet('Contour') else: fixed_points = fixedData.getPointSet('Centerline') moving_points = movingData.getPointSet('Centerline') fixed_res = fixedData.getResolution().tolist() moving_res = movingData.getResolution().tolist() fixed_points = fixed_points.copy()[npy.where(fixed_points[:, 0] >= 0)] moving_points = moving_points.copy()[npy.where( moving_points[:, 0] >= 0)] # Use the bifurcation as the initial position fixed_bif = db.getBifurcation(fixed_points) moving_bif = db.getBifurcation(moving_points) if (fixed_bif < 0) or (moving_bif < 0): fixed_min = 0 else: temp = moving_points[:, 2:] moving_delta = moving_bif - npy.min( temp[npy.where(npy.round(temp[:, 1]) == 0), 0]) fixed_min = fixed_bif - moving_delta * moving_res[-1] / fixed_res[ -1] #print moving_res #print fixed_res # Augmentation of pointset fixed = fixed_points[npy.where(fixed_points[:, 2] >= fixed_min)] moving = moving_points.copy() fixed = util.augmentPointset(fixed, int(fixed_res[-1] / moving_res[-1] + 0.5), moving.shape[0], fixed_bif) moving = util.augmentPointset( moving, int(moving_res[-1] / fixed_res[-1] + 0.5), fixed.shape[0], moving_bif) fixed = fixed[:, :3] moving = moving[:, :3] fixed[:, :3] *= fixed_res[:3] moving[:, :3] *= moving_res[:3] if (fixed_bif >= 0) and (moving_bif >= 0): fixed[:, 2] -= (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) print fixed.shape[0], moving.shape[0] #return None, None, None sourcePoints = vtk.vtkPoints() sourceVertices = vtk.vtkCellArray() for x in moving: id = sourcePoints.InsertNextPoint(x[0], x[1], x[2]) sourceVertices.InsertNextCell(1) sourceVertices.InsertCellPoint(id) source = vtk.vtkPolyData() source.SetPoints(sourcePoints) source.SetVerts(sourceVertices) targetPoints = vtk.vtkPoints() targetVertices = vtk.vtkCellArray() for x in fixed: id = targetPoints.InsertNextPoint(x[0], x[1], x[2]) targetVertices.InsertNextCell(1) targetVertices.InsertCellPoint(id) target = vtk.vtkPolyData() target.SetPoints(targetPoints) target.SetVerts(targetVertices) icp = vtk.vtkIterativeClosestPointTransform() icp.SetSource(source) icp.SetTarget(target) icp.GetLandmarkTransform().SetModeToRigidBody() icp.Modified() icp.Update() icp_filter = vtk.vtkTransformPolyDataFilter() icp_filter.SetInput(source) icp_filter.SetTransform(icp) icp_filter.Update() # Get the result transformation parameters matrix = icp.GetMatrix() T = ml.mat([ matrix.GetElement(0, 3), matrix.GetElement(1, 3), matrix.GetElement(2, 3) ]).T R = ml.mat([[ matrix.GetElement(0, 0), matrix.GetElement(0, 1), matrix.GetElement(0, 2) ], [ matrix.GetElement(1, 0), matrix.GetElement(1, 1), matrix.GetElement(1, 2) ], [ matrix.GetElement(2, 0), matrix.GetElement(2, 1), matrix.GetElement(2, 2) ]]).I if (fixed_bif >= 0) and (moving_bif >= 0): T[2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) moving_points = movingData.getPointSet('Contour').copy() moving_center = movingData.getPointSet('Centerline').copy() new_trans_points, result_center_points = util.resliceTheResultPoints( moving_points, moving_center, 20, moving_res, fixed_res, discard, R, T) T = -T T = R * T transform = sitk.Transform(3, sitk.sitkAffine) para = R.reshape(1, -1).tolist()[0] + T.T.tolist()[0] transform.SetParameters(para) movingImage = movingData.getSimpleITKImage() fixedImage = fixedData.getSimpleITKImage() resultImage = sitk.Resample(movingImage, fixedImage, transform, sitk.sitkLinear, 0, sitk.sitkFloat32) return sitk.GetArrayFromImage(resultImage), { 'Contour': trans_points, 'Centerline': result_center_points }, para + [0, 0, 0]
def register(self, fixedData, movingData, index = -1, isRigid = False, isTime = False): # For simple test if index == -1: if self.gui is not None: index = self.gui.getDataIndex({'Contour': 0, 'Centerline': 1}, 'Select the object') else: index = 1 if index is None: return None, None, None if index == 0: fixed_points = fixedData.getPointSet('Contour') moving_points = movingData.getPointSet('Contour') else: fixed_points = fixedData.getPointSet('Centerline') moving_points = movingData.getPointSet('Centerline') time1 = time.time() # Initial data fixed_res = fixedData.getResolution().tolist() moving_res = movingData.getResolution().tolist() fixed_points_con = fixedData.getPointSet('Contour') moving_points_con = movingData.getPointSet('Contour') fixed_points_cen = fixedData.getPointSet('Centerline') moving_points_cen = movingData.getPointSet('Centerline') fixed_points_ori = fixed_points.copy()[npy.where(fixed_points[:, 0] >= 0)] moving_points_ori = moving_points.copy()[npy.where(moving_points[:, 0] >= 0)] fixed_points_con_ori = fixed_points_con.copy()[npy.where(fixed_points_con[:, 0] >= 0)] moving_points_con_ori = moving_points_con.copy()[npy.where(moving_points_con[:, 0] >= 0)] fixed_points_cen_ori = fixed_points_cen.copy()[npy.where(fixed_points_cen[:, 0] >= 0)] moving_points_cen_ori = moving_points_cen.copy()[npy.where(moving_points_cen[:, 0] >= 0)] fixed_points = fixed_points_ori.copy() moving_points = moving_points_ori.copy() fixed_points_con = fixed_points_con_ori.copy() moving_points_con = moving_points_con_ori.copy() fixed_points_cen = fixed_points_cen_ori.copy() moving_points_cen = moving_points_cen_ori.copy() init_time = 0.0 time1 = time.time() fix_img = fixedData.getData() mov_img = movingData.getData() # Calculate the initial rigid transformation for 9 points T0 fix_key_point = eutil.getKeyPoints(fixed_points_cen, fixed_res) mov_key_point = eutil.getKeyPoints(moving_points_cen, moving_res) T0, mov_bif = eutil.getRigidTransform(fix_key_point, mov_key_point) # 4 * 4 Matrix moving_points = eutil.applyRigidTransformOnPoints(moving_points, moving_res, T0) moving_points_con = eutil.applyRigidTransformOnPoints(moving_points_con, moving_res, T0) moving_points_cen_result = eutil.applyRigidTransformOnPoints(moving_points_cen, moving_res, T0) crop_fixed_index, crop_moving_index = eutil.cropCenterline(fixed_points_cen, moving_points_cen_result, fixed_res, moving_res, fix_key_point[0, 2] / fixed_res[2], mov_bif[2] / moving_res[2]) # Use GMMREG for centerline-based rigid registration T1 gmm = GmmregPointsetRegistration(self.gui) new_fixedData = db.BasicData(fix_img, db.ImageInfo(fixedData.getInfo().data), {'Contour': fixed_points_con, 'Centerline': fixed_points_cen[crop_fixed_index]}) new_movingData = db.BasicData(mov_img, db.ImageInfo(movingData.getInfo().data), {'Contour': moving_points_con, 'Centerline': moving_points_cen_result[crop_moving_index]}) tmp_img, points, para = gmm.register(new_fixedData, new_movingData, index, False, "rigid") T1 = eutil.getMatrixFromGmmPara(para) T_init = T0 * T1 moving_points = points['Contour'].copy() moving_points_cen_result = points['Centerline'].copy() del new_movingData # Use GMMREG for centerline-based TPS registration if not isRigid: new_movingData = db.BasicData(mov_img, db.ImageInfo(fixedData.getInfo().data), {'Contour': moving_points, 'Centerline': moving_points_cen_result}) # The image has been resampled into fixed resolution tmp_img, points, para = gmm.register(new_fixedData, new_movingData, index, False, "EM_TPS") time2 = time.time() sa = SurfaceErrorAnalysis(None) dataset = db.BasicData(npy.array([[[0]]]), fixedData.getInfo(), points) mean_dis, mean_whole, max_dis, max_whole = sa.analysis(dataset, point_data_fix = fixed_points_con.copy(), useResult = True) del dataset print mean_dis print mean_whole if isTime: return tmp_img, points, [mean_dis, mean_whole], time2 - time1 return tmp_img, points, [mean_dis, mean_whole]
def analysis(self, data, point_data_fix = None, point_data_mov = None, point_data_mask = None, spacing_mov = None, useResult = False): if point_data_fix is None: point_data_fix = self.gui.dataModel[data.getFixedIndex()].getPointSet('Contour').copy() point_data_mov = self.gui.dataModel[data.getMovingIndex()].getPointSet('Contour').copy() point_data_mask = self.gui.dataModel[data.getMovingIndex()].getPointSet('Mask').copy() spacing_mov = self.gui.dataModel[data.getMovingIndex()].getResolution().tolist() self.spacing = data.getResolution().tolist() point_data_fix = point_data_fix[point_data_fix[:, 0] >= 0] bif = db.getBifurcation(point_data_fix) point_data_fix = util.augmentPointset(point_data_fix, 3, -1, bif, nn = 20) point_data_fix[:, :3] *= self.spacing[:3] if point_data_mov is not None: point_data_mov = point_data_mov[point_data_mov[:, 0] >= 0] if not useResult: para = npy.array(data.info.getData('transform')).flatten() point_data_result = point_data_mov.copy() for point in point_data_mask: point_data_result = npy.delete(point_data_result, npy.where((npy.abs(point_data_result[:, 2] - point[2]) < 0.0001) & (npy.round(point_data_result[:, -1]) == point[3])), axis = 0) point_data_result[:, :3] *= spacing_mov[:3] R = ml.mat(para[:9]).reshape(3, 3) T = ml.mat(para[9:12]).T if para.shape[0] > 12: C = ml.mat(para[12:]).T else: C = ml.zeros([3, 1], dtype = npy.float32) T = R.I * T T = -T point_data_result[:, :3] = util.applyTransformForPoints(point_data_result[:, :3], npy.array([1.0, 1, 1]), npy.array([1.0, 1, 1]), R, T, C) else: point_data_result = data.getPointSet('Contour').copy() point_data_result = point_data_result[point_data_result[:, -1] >= 0] point_data_result[:, :3] *= self.spacing[:3] targetPoints = [vtk.vtkPoints(), vtk.vtkPoints(), vtk.vtkPoints()] targetVertices = [vtk.vtkCellArray(), vtk.vtkCellArray(), vtk.vtkCellArray()] target = [vtk.vtkPolyData(), vtk.vtkPolyData(), vtk.vtkPolyData()] Locator = [vtk.vtkCellLocator(), vtk.vtkCellLocator(), vtk.vtkCellLocator()] label_dis = [3, 2, 1] for i in range(3): for x in point_data_fix[npy.round(point_data_fix[:, 3]) != label_dis[i]]: id = targetPoints[i].InsertNextPoint(x[0], x[1], x[2]) targetVertices[i].InsertNextCell(1) targetVertices[i].InsertCellPoint(id) target[i].SetPoints(targetPoints[i]) target[i].SetVerts(targetVertices[i]) Locator[i].SetDataSet(target[i]) Locator[i].SetNumberOfCellsPerBucket(1) Locator[i].BuildLocator() ''' Locator = vtk.vtkCellLocator() targetPoints = vtk.vtkPoints() targetVertices = vtk.vtkCellArray() target = vtk.vtkPolyData() for x in point_data_fix: id = targetPoints.InsertNextPoint(x[0], x[1], x[2]) targetVertices.InsertNextCell(1) targetVertices.InsertCellPoint(id) target.SetPoints(targetPoints) target.SetVerts(targetVertices) Locator.SetDataSet(target) Locator.SetNumberOfCellsPerBucket(1) Locator.BuildLocator() ''' id1 = id2 = vtk.mutable(0) dist = vtk.mutable(0.0) outPoint = [0.0, 0.0, 0.0] cnt_num = npy.array([0, 0, 0]) mean_dis = npy.array([0.0, 0.0, 0.0]) max_dis = npy.array([0.0, 0.0, 0.0]) for pt in point_data_result: cnt = int(pt[-1] + 0.5) Locator[cnt].FindClosestPoint(pt[:3].tolist(), outPoint, id1, id2, dist) dis = npy.sqrt(npy.sum((npy.array(outPoint) - pt[:3]) ** 2)) mean_dis[cnt] += dis max_dis[cnt] = npy.max([max_dis[cnt], dis]) cnt_num[cnt] += 1 cnt_total = npy.sum(cnt_num) mean_whole = npy.sum(mean_dis) / cnt_total mean_dis /= cnt_num mean_dis[mean_dis != mean_dis] = 0 # Replace the NAN in the mean distance max_whole = npy.max(max_dis) if self.gui is not None: message = "Error on Vessel 0: %0.2fmm (Total %d slices)\nError on Vessel 1: %0.2fmm (Total %d slices)\nError on Vessel 2: %0.2fmm (Total %d slices)\nWhole Error: %0.2fmm (Total %d slices)\n" \ % (mean_dis[0], cnt_num[0], mean_dis[1], cnt_num[1], mean_dis[2], cnt_num[2], mean_whole, cnt_total) + \ "-----------------------------------------------------------------------------\n" + \ "Max Error on Vessel 0: %0.2fmm\nMax Error on Vessel 1: %0.2fmm\nMax Error on Vessel 2: %0.2fmm\nTotal Max Error: %0.2fmm" \ % (max_dis[0], max_dis[1], max_dis[2], npy.max(max_dis)); self.gui.showErrorMessage("Centerline Registration Error", message) return mean_dis, mean_whole, max_dis, max_whole
def process(self, dataset, i): def autoDetectContour(point, cnt, start, end, delta, res, type): self.new_points = npy.append(self.new_points, point, 0) points = point[:, :-2] d = 20 count = 0 for i in range(start + delta, end + delta, delta): center = calCentroidFromContour(points).reshape(2) image = dataset[type].getData()[i, :, :].transpose().copy() image = (image - npy.min(image)) / (npy.max(image) - npy.min(image)) * 255 down = npy.max([npy.ceil(center[0] - d / res[0]), 0]) up = npy.min( [npy.floor(center[0] + d / res[0]), image.shape[0]]) left = npy.max([npy.ceil(center[1] - d / res[1]), 0]) right = npy.min( [npy.floor(center[1] + d / res[1]), image.shape[1]]) crop_image = image[down:up, left:right] center -= [down, left] result = ac_segmentation(center, crop_image) a1 = ac_area(points.transpose(), image.shape) a2 = ac_area(result, crop_image.shape) rate = a2 * 1.0 / a1 if rate >= min(1.5 + count * 0.2, 2.1) or rate <= 0.7: temp_array = points.copy() if cnt != 1 and rate > 0.7: count += 1 else: temp_array = result.transpose().copy() temp_array[:, :2] += [down, left] count = 0 points = temp_array.copy() temp_array = npy.insert(temp_array, 2, [[i], [cnt]], 1) self.new_points = npy.append(self.new_points, temp_array, 0) sys.stdout.write(str(i) + ',') sys.stdout.flush() print ' ' # Segmentation of data print 'Segment Data %s...' % self.ini.file.name_result[i] tmp = dataset['fix'].pointSet.data['Contour'] tmp = tmp[tmp[:, 0] >= 0] self.new_points = npy.array([[-1, -1, -1, -1]], dtype=npy.float32) bottom = int(npy.round(npy.min(tmp[:, 2]))) bif = int(db.getBifurcation(tmp) + 0.5) up = int(npy.round(npy.max(tmp[:, 2]))) bottom += (bif - bottom) / 2 up -= (up - bif) / 2 point_vital = [0] * 3 point_vital[0] = tmp[(npy.round(tmp[:, -1]) == 0) & (npy.round(tmp[:, 2]) == bottom)].copy() point_vital[1] = tmp[(npy.round(tmp[:, -1]) == 1) & (npy.round(tmp[:, 2]) == up)].copy() point_vital[2] = tmp[(npy.round(tmp[:, -1]) == 2) & (npy.round(tmp[:, 2]) == up)].copy() autoDetectContour(point_vital[0], 0, bottom, bif, 1, dataset['fix'].getResolution().tolist(), 'fix') autoDetectContour(point_vital[1], 1, up, bif, -1, dataset['fix'].getResolution().tolist(), 'fix') autoDetectContour(point_vital[2], 2, up, bif, -1, dataset['fix'].getResolution().tolist(), 'fix') print ' ' print 'Finish segmentation for fix data. ' pointset = {'Contour': self.new_points} dataset['fix'].pointSet.data['Centerline'] = calCenterlineFromContour( pointset) self.new_points_fix = self.new_points.copy() # For mov data tmp = dataset['mov'].pointSet.data['Contour'] tmp = tmp[tmp[:, 0] >= 0] self.new_points = npy.array([[-1, -1, -1, -1]], dtype=npy.float32) bottom = int(npy.round(npy.min(tmp[:, 2]))) bif = int(db.getBifurcation(tmp) + 0.5) up = int(npy.round(npy.max(tmp[:, 2]))) bottom += (bif - bottom) / 2 up -= (up - bif) / 2 point_vital = [0] * 3 point_vital[0] = tmp[(npy.round(tmp[:, -1]) == 0) & (npy.round(tmp[:, 2]) == bottom)].copy() point_vital[1] = tmp[(npy.round(tmp[:, -1]) == 1) & (npy.round(tmp[:, 2]) == up)].copy() point_vital[2] = tmp[(npy.round(tmp[:, -1]) == 2) & (npy.round(tmp[:, 2]) == up)].copy() autoDetectContour(point_vital[0], 0, bottom, bif, 1, dataset['mov'].getResolution().tolist(), 'mov') autoDetectContour(point_vital[1], 1, up, bif, -1, dataset['mov'].getResolution().tolist(), 'mov') autoDetectContour(point_vital[2], 2, up, bif, -1, dataset['mov'].getResolution().tolist(), 'mov') print ' ' print 'Finish segmentation for mov data. ' pointset = {'Contour': self.new_points} dataset['mov'].pointSet.data['Centerline'] = calCenterlineFromContour( pointset) self.new_points_mov = self.new_points.copy() # ICP with centerline without label print 'Register Data %s with ICP(centerline) without label...' % self.ini.file.name_result[ i] data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1, op=True) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole dice_index, dice_index_all = self.areaerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet2.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet2.write(j + 1, i + 2, mean_dis[j]) self.sheet2.write(j + 5, i + 2, max_dis[j]) self.sheet2.write(j + 9, i + 2, dice_index[j]) self.sheet2.write(4, i + 2, mean_whole) self.sheet2.write(8, i + 2, max_whole) self.sheet2.write(12, i + 2, dice_index_all) self.book.save(self.path + self.ini.file.savedir + 'multicontrast_seg_feature.xls') del data, point, resultData # ICP with centerline with label print 'Register Data %s with ICP(centerline) with label...' % self.ini.file.name_result[ i] data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1, op=False) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole dice_index, dice_index_all = self.areaerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet4.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet4.write(j + 1, i + 2, mean_dis[j]) self.sheet4.write(j + 5, i + 2, max_dis[j]) self.sheet4.write(j + 9, i + 2, dice_index[j]) self.sheet4.write(4, i + 2, mean_whole) self.sheet4.write(8, i + 2, max_whole) self.sheet4.write(12, i + 2, dice_index_all) self.book.save(self.path + self.ini.file.savedir + 'multicontrast_seg_feature.xls') del data, point, resultData fix_points = dataset['fix'].getPointSet('Contour').copy() dataset['fix'].pointSet.data['Contour'] = self.new_points_fix mov_points = dataset['mov'].getPointSet('Contour').copy() dataset['mov'].pointSet.data['Contour'] = self.new_points_mov print 'Saving Data %s...' % self.ini.file.name_result[i] db.saveMatData( self.path + self.ini.file.savedir + self.ini.file.name_result[i] + '_snap.mat', [dataset['fix']], 0) db.saveMatData( self.path + self.ini.file.savedir + self.ini.file.name_result[i] + '_merge.mat', [dataset['mov']], 0) print 'Done!' # ICP with contour without label print 'Register Data %s with ICP(contour) without label...' % self.ini.file.name_result[ i] data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 0, op=False) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, fix_points.copy(), mov_points.copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole para = resultData.info.getData('transform') R = ml.mat(para[:9]).reshape(3, 3) T = ml.mat(para[9:12]).T T = R.I * T T = -T tmp_con, result_center_points = util.resliceTheResultPoints( mov_points, None, 20, dataset['mov'].getResolution().tolist(), dataset['fix'].getResolution().tolist(), False, R, T) resultData.pointSet.data['Contour'] = tmp_con dice_index, dice_index_all = self.areaerror.analysis( resultData, fix_points.copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet1.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet1.write(j + 1, i + 2, mean_dis[j]) self.sheet1.write(j + 5, i + 2, max_dis[j]) self.sheet1.write(j + 9, i + 2, dice_index[j]) self.sheet1.write(4, i + 2, mean_whole) self.sheet1.write(8, i + 2, max_whole) self.sheet1.write(12, i + 2, dice_index_all) self.book.save(self.path + self.ini.file.savedir + 'multicontrast_seg_feature.xls') del data, point, resultData # ICP with contour with label print 'Register Data %s with ICP(contour) with label...' % self.ini.file.name_result[ i] data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 0, op=True) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, fix_points.copy(), mov_points.copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole para = resultData.info.getData('transform') R = ml.mat(para[:9]).reshape(3, 3) T = ml.mat(para[9:12]).T T = R.I * T T = -T tmp_con, result_center_points = util.resliceTheResultPoints( mov_points, None, 20, dataset['mov'].getResolution().tolist(), dataset['fix'].getResolution().tolist(), False, R, T) resultData.pointSet.data['Contour'] = tmp_con dice_index, dice_index_all = self.areaerror.analysis( resultData, fix_points.copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet3.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet3.write(j + 1, i + 2, mean_dis[j]) self.sheet3.write(j + 5, i + 2, max_dis[j]) self.sheet3.write(j + 9, i + 2, dice_index[j]) self.sheet3.write(4, i + 2, mean_whole) self.sheet3.write(8, i + 2, max_whole) self.sheet3.write(12, i + 2, dice_index_all) self.book.save(self.path + self.ini.file.savedir + 'multicontrast_seg_feature.xls') del data, point, resultData del self.new_points, fix_points, self.new_points_fix, self.new_points_mov, mov_points, tmp_con, result_center_points
def register(self, fixedData, movingData, index = -1, discard = False, delta = 0, fov = 9999999.0, down_fix = 1, down_mov = 1, occ = 9999999.0, op = False, useMask = False, isTime = False, MaxRate = 0.2, aug = False, distance_fix = 0.3, distance_mov = 0.1): time1 = time.time() if index == -1: index = self.gui.getDataIndex({'Contour': 0, 'Centerline': 1}, 'Select the object') if index is None: return None, None, None if index == 0: fixed_points = fixedData.getPointSet('Contour').copy() moving_points = movingData.getPointSet('Contour').copy() else: fixed_points = fixedData.getPointSet('Centerline').copy() moving_points = movingData.getPointSet('Centerline').copy() fixed_bif = db.getBifurcation(fixed_points) moving_bif = db.getBifurcation(moving_points) if useMask: mask_points = movingData.getPointSet('Mask') for point in mask_points: moving_points = npy.delete(moving_points, npy.where((npy.abs(moving_points[:, 2] - point[2]) < 0.0001) & (npy.round(moving_points[:, -1]) == point[3])), axis = 0) fixed_res = fixedData.getResolution().tolist() moving_res = movingData.getResolution().tolist() fixed_points = fixed_points[npy.where(fixed_points[:, 0] >= 0)] moving_points = moving_points[npy.where(moving_points[:, 0] >= 0)] # Use the bifurcation as the initial position if (fixed_bif < 0) or (moving_bif < 0): fixed_min = 0 # Augmentation of pointset fixed = fixed_points.copy() moving = moving_points.copy() if index == 1 and aug: fixed = util.augmentCenterline(fixed, 1, 10) moving = util.augmentCenterline(moving, 1, 10) fix_dis = util.getAxisSin(fixed, 3 / fixed_res[2]) * distance_fix mov_dis = util.getAxisSin(moving, 3 / moving_res[2]) * distance_mov fixed = util.resampleCenterline(fixed, fix_dis / fixed_res[2]) moving = util.resampleCenterline(moving, mov_dis / moving_res[2]) fixed = fixed[npy.cast[npy.int32](npy.abs(fixed[:, 2] - fixed_bif)) % down_fix == 0] moving = moving[npy.cast[npy.int32](npy.abs(moving[:, 2] - moving_bif)) % down_mov == 0] fixed[:, :3] *= fixed_res[:3] moving[:, :3] *= moving_res[:3] if (fixed_bif >= 0) and (moving_bif >= 0): fixed[:, 2] -= (fixed_bif * fixed_res[2] - moving_bif * moving_res[2] + delta) # Prepare for ICP LandmarkTransform = vtk.vtkLandmarkTransform() LandmarkTransform.SetModeToRigidBody() MaxIterNum = 50 #MaxNum = 600 MaxNum = int(MaxRate * moving.shape[0] + 0.5) targetPoints = [vtk.vtkPoints(), vtk.vtkPoints(), vtk.vtkPoints()] targetVertices = [vtk.vtkCellArray(), vtk.vtkCellArray(), vtk.vtkCellArray()] target = [vtk.vtkPolyData(), vtk.vtkPolyData(), vtk.vtkPolyData()] Locator = [vtk.vtkCellLocator(), vtk.vtkCellLocator(), vtk.vtkCellLocator()] if index == 0: if not op: label_dis = [3, 3, 3] else: label_dis = [3, 2, 1] else: if op: label_dis = [3, 3, 3] else: label_dis = [3, 2, 1] for i in range(3): for x in fixed[npy.round(fixed[:, 3]) != label_dis[i]]: id = targetPoints[i].InsertNextPoint(x[0], x[1], x[2]) targetVertices[i].InsertNextCell(1) targetVertices[i].InsertCellPoint(id) target[i].SetPoints(targetPoints[i]) target[i].SetVerts(targetVertices[i]) Locator[i].SetDataSet(target[i]) Locator[i].SetNumberOfCellsPerBucket(1) Locator[i].BuildLocator() step = 1 if moving.shape[0] > MaxNum: ind = moving[:, 2].argsort() moving = moving[ind, :] step = moving.shape[0] / MaxNum nb_points = moving.shape[0] / step accumulate = vtk.vtkTransform() accumulate.PostMultiply() points1 = vtk.vtkPoints() points1.SetNumberOfPoints(nb_points) label = npy.zeros([MaxNum * 2], dtype = npy.int8) j = 0 for i in range(nb_points): points1.SetPoint(i, moving[j][0], moving[j][1], moving[j][2]) label[i] = moving[j][3] j += step closestp = vtk.vtkPoints() closestp.SetNumberOfPoints(nb_points) points2 = vtk.vtkPoints() points2.SetNumberOfPoints(nb_points) id1 = id2 = vtk.mutable(0) dist = vtk.mutable(0.0) outPoint = [0.0, 0.0, 0.0] p1 = [0.0, 0.0, 0.0] p2 = [0.0, 0.0, 0.0] iternum = 0 a = points1 b = points2 ''' path = sys.argv[0] if os.path.isfile(path): path = os.path.dirname(path) path += '/Data/Transform' wfile = open("%s/transform.txt" % path, 'w') matrix = accumulate.GetMatrix() T = ml.mat([matrix.GetElement(0, 3), matrix.GetElement(1, 3), matrix.GetElement(2, 3)]).T; R = ml.mat([[matrix.GetElement(0, 0), matrix.GetElement(0, 1), matrix.GetElement(0, 2)], [matrix.GetElement(1, 0), matrix.GetElement(1, 1), matrix.GetElement(1, 2)], [matrix.GetElement(2, 0), matrix.GetElement(2, 1), matrix.GetElement(2, 2)]]).I if (fixed_bif >= 0) and (moving_bif >= 0): T[2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2] + delta) saveTransform(wfile, T, R) ''' while True: for i in range(nb_points): Locator[label[i]].FindClosestPoint(a.GetPoint(i), outPoint, id1, id2, dist) closestp.SetPoint(i, outPoint) LandmarkTransform.SetSourceLandmarks(a) LandmarkTransform.SetTargetLandmarks(closestp) LandmarkTransform.Update() accumulate.Concatenate(LandmarkTransform.GetMatrix()) iternum += 1 if iternum >= MaxIterNum: break dist_err = 0 for i in range(nb_points): a.GetPoint(i, p1) LandmarkTransform.InternalTransformPoint(p1, p2) b.SetPoint(i, p2) dist_err += npy.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2 + (p1[2] - p2[2]) ** 2) dist_err /= nb_points print "iter = %d: %f" % (iternum, dist_err) ''' matrix = accumulate.GetMatrix() T = ml.mat([matrix.GetElement(0, 3), matrix.GetElement(1, 3), matrix.GetElement(2, 3)]).T; R = ml.mat([[matrix.GetElement(0, 0), matrix.GetElement(0, 1), matrix.GetElement(0, 2)], [matrix.GetElement(1, 0), matrix.GetElement(1, 1), matrix.GetElement(1, 2)], [matrix.GetElement(2, 0), matrix.GetElement(2, 1), matrix.GetElement(2, 2)]]).I; if (fixed_bif >= 0) and (moving_bif >= 0): T[2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) saveTransform(wfile, T, R) ''' b, a = a, b time2 = time.time() #wfile.close() # Get the result transformation parameters matrix = accumulate.GetMatrix() T = ml.mat([matrix.GetElement(0, 3), matrix.GetElement(1, 3), matrix.GetElement(2, 3)]).T R = ml.mat([[matrix.GetElement(0, 0), matrix.GetElement(0, 1), matrix.GetElement(0, 2)], [matrix.GetElement(1, 0), matrix.GetElement(1, 1), matrix.GetElement(1, 2)], [matrix.GetElement(2, 0), matrix.GetElement(2, 1), matrix.GetElement(2, 2)]]).I #T = ml.mat([0, 0, 0]).T #R = ml.mat([[1, 0, 0], [0, 1, 0], [0, 0, 1]]).T if (fixed_bif >= 0) and (moving_bif >= 0): T[2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2] + delta) # Resample the moving contour moving_points = movingData.getPointSet('Contour').copy() moving_center = movingData.getPointSet('Centerline').copy() #new_trans_points, result_center_points = util.resliceTheResultPoints(moving_points, moving_center, 20, moving_res, fixed_res, discard, R, T) new_trans_points, result_center_points = moving_points, moving_center result_center_points[:, :3] = util.applyTransformForPoints(result_center_points[:, :3], moving_res, fixed_res, R, T, ml.zeros([3, 1], dtype = npy.float32)) new_trans_points[:, :3] = util.applyTransformForPoints(new_trans_points[:, :3], moving_res, fixed_res, R, T, ml.zeros([3, 1], dtype = npy.float32)) T = -T T = R * T transform = sitk.Transform(3, sitk.sitkAffine) para = R.reshape(1, -1).tolist()[0] + T.T.tolist()[0] transform.SetParameters(para) movingImage = movingData.getSimpleITKImage() fixedImage = fixedData.getSimpleITKImage() resultImage = sitk.Resample(movingImage, fixedImage, transform, sitk.sitkLinear, 0, sitk.sitkFloat32) if isTime: return sitk.GetArrayFromImage(resultImage), {'Contour': new_trans_points, 'Centerline': result_center_points}, para + [0, 0, 0], time2 - time1 return sitk.GetArrayFromImage(resultImage), {'Contour': new_trans_points, 'Centerline': result_center_points}, para + [0, 0, 0]
def process(self, dataset, i): def autoDetectContour(point, cnt, start, end, delta): self.new_points = npy.append(self.new_points, point, 0) points = point[:, :-2] count = 0 for j in range(start + delta, end + delta, delta): center = calCentroidFromContour(points).reshape(2) image = dataset['fix'].getData()[j, :, :].transpose().copy() image = (image - npy.min(image)) / (npy.max(image) - npy.min(image)) * 255 result = ac_segmentation(center, image) a1 = ac_area(points.transpose(), image.shape) a2 = ac_area(result, image.shape) rate = a2 * 1.0 / a1 if rate >= min(1.5 + count * 0.2, 2.1) or rate <= 0.7: temp_array = points.copy() if cnt != 1 and rate > 0.7: count += 1 else: temp_array = result.transpose().copy() count = 0 points = temp_array.copy() temp_array = npy.insert(temp_array, 2, [[j], [cnt]], 1) self.new_points = npy.append(self.new_points, temp_array, 0) sys.stdout.write(str(j) + ',') sys.stdout.flush() print ' ' print 'Segment Data %s...' % self.ini.file.name_result[i] tmp = dataset['fix'].pointSet.data['Contour'] tmp = tmp[tmp[:, 0] >= 0] self.new_points = npy.array([[-1, -1, -1, -1]], dtype=npy.float32) time1 = time.time() bottom = int(npy.round(npy.min(tmp[:, 2]))) bif = int(db.getBifurcation(tmp) + 0.5) up = int(npy.round(npy.max(tmp[:, 2]))) point_vital = [0] * 3 point_vital[0] = tmp[(npy.round(tmp[:, -1]) == 0) & (npy.round(tmp[:, 2]) == bottom)].copy() point_vital[1] = tmp[(npy.round(tmp[:, -1]) == 1) & (npy.round(tmp[:, 2]) == up)].copy() point_vital[2] = tmp[(npy.round(tmp[:, -1]) == 2) & (npy.round(tmp[:, 2]) == up)].copy() autoDetectContour(point_vital[0], 0, bottom, bif, 1) autoDetectContour(point_vital[1], 1, up, bif, -1) autoDetectContour(point_vital[2], 2, up, bif, -1) time2 = time.time() ''' # Use centerline for contour j = 0 for center in tmp: image = dataset['fix'].getData()[npy.round(center[2]), :, :].transpose().copy() image = (image - npy.min(image)) / (npy.max(image) - npy.min(image)) * 255 result = ac_segmentation(center[:2], image) point_array = npy.insert(result.transpose(), 2, [[center[2]],[center[3]]], axis = 1) new_points = npy.append(new_points, point_array, 0) j += 1 if j % 10 == 0: sys.stdout.write(str(j) + ',') sys.stdout.flush() ''' print ' ' print 'Done! Time for segmentation is %0.2fs' % (time2 - time1) pointset = {'Contour': self.new_points} pointset['Centerline'] = calCenterlineFromContour(pointset) print 'Saving Data %s...' % self.ini.file.name_result[i] new_data = db.BasicData(dataset['fix'].data, db.ImageInfo(dataset['fix'].info.data), pointset) db.saveMatData( self.savepath + self.ini.file.name_result[i] + '_mr.mat', [new_data], 0) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.contourerror.analysis( new_data, dataset['fix'].getPointSet('Contour').copy()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole self.sheet1.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet1.write(j + 1, i + 2, mean_dis[j]) self.sheet1.write(4, i + 2, mean_whole) self.sheet1.write(5, i + 2, time2 - time1) self.book.save(self.path + self.ini.file.savedir + 'Test_segmentation_final_refined.xls') # ICP with centerline print 'Register Data %s with ICP(centerline)...' % self.ini.file.name_result[ i] time1 = time.time() data, point, para = self.icp.register(new_data, dataset['mov'], 1) time2 = time.time() print 'Done! Time for registration is %0.2fs' % (time2 - time1) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) mean_dis, mean_whole, max_dis, max_whole = self.contourerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole dice_index, dice_index_all = self.areaerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet2.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet2.write(j + 1, i + 2, mean_dis[j]) self.sheet2.write(j + 5, i + 2, max_dis[j]) self.sheet2.write(j + 9, i + 2, dice_index[j]) self.sheet2.write(4, i + 2, mean_whole) self.sheet2.write(8, i + 2, max_whole) self.sheet2.write(12, i + 2, dice_index_all) self.sheet2.write(13, i + 2, time2 - time1) self.book.save(self.path + self.ini.file.savedir + 'Test_segmentation_final_refined2.xls') del data, point, resultData
def analysis(self, data, point_data_fix=None, point_data_mov=None, point_data_mask=None, spacing_mov=None, useResult=False): if point_data_fix is None: point_data_fix = self.gui.dataModel[ data.getFixedIndex()].getPointSet('Contour').copy() point_data_mov = self.gui.dataModel[ data.getMovingIndex()].getPointSet('Contour').copy() point_data_mask = self.gui.dataModel[ data.getMovingIndex()].getPointSet('Mask').copy() spacing_mov = self.gui.dataModel[ data.getMovingIndex()].getResolution().tolist() self.spacing = data.getResolution().tolist() point_data_fix = point_data_fix[point_data_fix[:, 0] >= 0] bif = db.getBifurcation(point_data_fix) point_data_fix = util.augmentPointset(point_data_fix, 3, -1, bif, nn=20) point_data_fix[:, :3] *= self.spacing[:3] if point_data_mov is not None: point_data_mov = point_data_mov[point_data_mov[:, 0] >= 0] if not useResult: para = npy.array(data.info.getData('transform')).flatten() point_data_result = point_data_mov.copy() for point in point_data_mask: point_data_result = npy.delete( point_data_result, npy.where( (npy.abs(point_data_result[:, 2] - point[2]) < 0.0001) & (npy.round(point_data_result[:, -1]) == point[3])), axis=0) point_data_result[:, :3] *= spacing_mov[:3] R = ml.mat(para[:9]).reshape(3, 3) T = ml.mat(para[9:12]).T if para.shape[0] > 12: C = ml.mat(para[12:]).T else: C = ml.zeros([3, 1], dtype=npy.float32) T = R.I * T T = -T point_data_result[:, :3] = util.applyTransformForPoints( point_data_result[:, :3], npy.array([1.0, 1, 1]), npy.array([1.0, 1, 1]), R, T, C) else: point_data_result = data.getPointSet('Contour').copy() point_data_result = point_data_result[point_data_result[:, -1] >= 0] point_data_result[:, :3] *= self.spacing[:3] targetPoints = [vtk.vtkPoints(), vtk.vtkPoints(), vtk.vtkPoints()] targetVertices = [ vtk.vtkCellArray(), vtk.vtkCellArray(), vtk.vtkCellArray() ] target = [vtk.vtkPolyData(), vtk.vtkPolyData(), vtk.vtkPolyData()] Locator = [ vtk.vtkCellLocator(), vtk.vtkCellLocator(), vtk.vtkCellLocator() ] label_dis = [3, 2, 1] for i in range(3): for x in point_data_fix[ npy.round(point_data_fix[:, 3]) != label_dis[i]]: id = targetPoints[i].InsertNextPoint(x[0], x[1], x[2]) targetVertices[i].InsertNextCell(1) targetVertices[i].InsertCellPoint(id) target[i].SetPoints(targetPoints[i]) target[i].SetVerts(targetVertices[i]) Locator[i].SetDataSet(target[i]) Locator[i].SetNumberOfCellsPerBucket(1) Locator[i].BuildLocator() ''' Locator = vtk.vtkCellLocator() targetPoints = vtk.vtkPoints() targetVertices = vtk.vtkCellArray() target = vtk.vtkPolyData() for x in point_data_fix: id = targetPoints.InsertNextPoint(x[0], x[1], x[2]) targetVertices.InsertNextCell(1) targetVertices.InsertCellPoint(id) target.SetPoints(targetPoints) target.SetVerts(targetVertices) Locator.SetDataSet(target) Locator.SetNumberOfCellsPerBucket(1) Locator.BuildLocator() ''' id1 = id2 = vtk.mutable(0) dist = vtk.mutable(0.0) outPoint = [0.0, 0.0, 0.0] cnt_num = npy.array([0, 0, 0]) mean_dis = npy.array([0.0, 0.0, 0.0]) max_dis = npy.array([0.0, 0.0, 0.0]) for pt in point_data_result: cnt = int(pt[-1] + 0.5) Locator[cnt].FindClosestPoint(pt[:3].tolist(), outPoint, id1, id2, dist) dis = npy.sqrt(npy.sum((npy.array(outPoint) - pt[:3])**2)) mean_dis[cnt] += dis max_dis[cnt] = npy.max([max_dis[cnt], dis]) cnt_num[cnt] += 1 cnt_total = npy.sum(cnt_num) mean_whole = npy.sum(mean_dis) / cnt_total mean_dis /= cnt_num mean_dis[ mean_dis != mean_dis] = 0 # Replace the NAN in the mean distance max_whole = npy.max(max_dis) if self.gui is not None: message = "Error on Vessel 0: %0.2fmm (Total %d slices)\nError on Vessel 1: %0.2fmm (Total %d slices)\nError on Vessel 2: %0.2fmm (Total %d slices)\nWhole Error: %0.2fmm (Total %d slices)\n" \ % (mean_dis[0], cnt_num[0], mean_dis[1], cnt_num[1], mean_dis[2], cnt_num[2], mean_whole, cnt_total) + \ "-----------------------------------------------------------------------------\n" + \ "Max Error on Vessel 0: %0.2fmm\nMax Error on Vessel 1: %0.2fmm\nMax Error on Vessel 2: %0.2fmm\nTotal Max Error: %0.2fmm" \ % (max_dis[0], max_dis[1], max_dis[2], npy.max(max_dis)) self.gui.showErrorMessage("Centerline Registration Error", message) return mean_dis, mean_whole, max_dis, max_whole
def register(self, fixedData, movingData, index=-1, discard=False, method="EM_TPS", execute=True, isTime=False): if index == -1: index = self.gui.getDataIndex({ 'Contour': 0, 'Centerline': 1 }, 'Select the object') if index is None: return None, None, None if index == 0: fixed_points = fixedData.getPointSet('Contour') moving_points = movingData.getPointSet('Contour') else: fixed_points = fixedData.getPointSet('Centerline') moving_points = movingData.getPointSet('Centerline') time1 = time.time() fixed_res = fixedData.getResolution().tolist() moving_res = movingData.getResolution().tolist() fixed_points = fixed_points.copy()[npy.where(fixed_points[:, -1] >= 0)] moving_points = moving_points.copy()[npy.where( moving_points[:, -1] >= 0)] # Use the bifurcation as the initial position fixed_bif = db.getBifurcation(fixed_points) moving_bif = db.getBifurcation(moving_points) if (fixed_bif < 0) or (moving_bif < 0): fixed_min = 0 else: temp = moving_points[:, 2:] moving_delta = moving_bif - npy.min( temp[npy.where(npy.round(temp[:, 1]) == 0), 0]) #fixed_min = 0 # Augmentation of pointset fixed = fixed_points.copy() tmp_fix = fixedData.getPointSet('Centerline') tmp_fix = tmp_fix[tmp_fix[:, -1] >= 0].copy() ctrl_pts = gutil.getControlPoints(tmp_fix, 1.0 / fixed_res[2]) moving = moving_points.copy() fixed = fixed[:, :3] moving = moving[:, :3] fixed[:, :3] *= fixed_res[:3] ctrl_pts *= fixed_res[:3] ctrl_pts_backup = ctrl_pts.copy() moving[:, :3] *= moving_res[:3] if (fixed_bif >= 0) and (moving_bif >= 0): fixed[:, 2] -= (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) ctrl_pts[:, 2] -= (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) #print fixed.shape[0], moving.shape[0] eg.initial_data(fixed, moving, ctrl_pts) if execute: code = eg.run_executable(method=method) #print code if code != 0: print "GMM Fail!" return None, None, None trans, para, para2 = eg.get_final_result(methodname=method) time2 = time.time() # Clear the temp files #eg.clear_temp_file() # Get the result transformation parameters if method == 'rigid': S1 = ml.eye(3, dtype=npy.float32) * para2[3] C = npy.asmatrix(para2[:3]).T C2 = npy.asmatrix(para2[4:7]).T T0 = npy.asmatrix(para[4:]).T R = util.quaternion2rotation(para[:4]) T = S1 * T0 + C2 - C if (fixed_bif >= 0) and (moving_bif >= 0): T[2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) moving_points = movingData.getPointSet('Contour').copy() moving_center = movingData.getPointSet('Centerline').copy() #new_trans_points, result_center_points = util.resliceTheResultPoints(moving_points, moving_center, 20, moving_res, fixed_res, discard, R, T, C) new_trans_points = util.applyTransformForPoints( moving_points, moving_res, fixed_res, R, T, C) result_center_points = util.applyTransformForPoints( moving_center, moving_res, fixed_res, R, T, C) T = -T T = R * T """ # Copy the output points of GMMREG for test new_trans_points = trans if (fixed_bif >= 0) and (moving_bif >= 0): new_trans_points[:, 2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) new_trans_points[:, :3] /= fixed_res[:3] new_trans_points = npy.insert(new_trans_points, [new_trans_points.shape[1]], moving_points[:, -1].reshape(-1, 1), axis = 1) new_trans_points = npy.append(new_trans_points, npy.array([[-1, -1, -1, -1]]), axis = 0) #result_center_points = movingData.getPointSet('Centerline').copy() result_center_points = movingData.getPointSet('Contour').copy() """ transform = sitk.Transform(3, sitk.sitkAffine) para = R.reshape(1, -1).tolist()[0] + T.T.tolist()[0] transform.SetParameters(para) transform.SetFixedParameters(C.T.tolist()[0]) #movingImage = movingData.getSimpleITKImage() #fixedImage = fixedData.getSimpleITKImage() #resultImage = sitk.Resample(movingImage, fixedImage, transform, sitk.sitkLinear, 0, sitk.sitkFloat32) if isTime: #return sitk.GetArrayFromImage(resultImage), {'Contour': new_trans_points, 'Centerline': result_center_points}, para + C.T.tolist()[0], time2 - time1 return movingData.getData().copy(), { 'Contour': new_trans_points, 'Centerline': result_center_points }, para + C.T.tolist()[0], time2 - time1 #return sitk.GetArrayFromImage(resultImage), {'Contour': new_trans_points, 'Centerline': result_center_points}, para + C.T.tolist()[0] return movingData.getData().copy(), { 'Contour': new_trans_points, 'Centerline': result_center_points }, para + C.T.tolist()[0] else: # EM_TPS moving_points = movingData.getPointSet('Contour').copy() moving_points = moving_points[npy.where(moving_points[:, 0] >= 0)] moving = moving_points[:, :3].copy() moving *= moving_res[:3] m = moving.shape[0] n = ctrl_pts.shape[0] M = ml.mat(moving.copy()) C2 = npy.asmatrix(para2[4:7]) C2 = ml.repmat(C2, m, 1) C3 = npy.asmatrix(para2[7:]) C3 = ml.repmat(C3, n, 1) ctrl_pts -= C3 ctrl_pts /= para2[3] C = npy.asmatrix(para2[:3]) C = ml.repmat(C, m, 1) moving -= C moving /= para2[3] basis = ml.zeros([m, n], dtype=npy.float32) basis[:, 0] = 1 basis[:, 1:4] = moving U = gutil.ComputeTPSKernel(moving, ctrl_pts) basis[:, 4:] = U * ml.mat(trans) #print npy.array(basis) T = basis * ml.mat(para) T *= para2[3] T += C2 - C if (fixed_bif >= 0) and (moving_bif >= 0): T[:, 2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) M += T new_trans_points = npy.array(M).copy() new_trans_points[:, :3] /= fixed_res[:3] new_trans_points = npy.insert(new_trans_points, [new_trans_points.shape[1]], moving_points[:, -1].reshape(-1, 1), axis=1) new_trans_points = npy.append(new_trans_points, npy.array([[-1, -1, -1, -1]]), axis=0) moving_points = movingData.getPointSet('Centerline').copy() moving_points = moving_points[npy.where(moving_points[:, 0] >= 0)] moving = moving_points[:, :3].copy() moving *= moving_res[:3] m = moving.shape[0] M = ml.mat(moving.copy()) C2 = npy.asmatrix(para2[4:7]) C2 = ml.repmat(C2, m, 1) C = npy.asmatrix(para2[:3]) C = ml.repmat(C, m, 1) moving -= C moving /= para2[3] basis = ml.zeros([m, n], dtype=npy.float32) basis[:, 0] = 1 basis[:, 1:4] = moving U = gutil.ComputeTPSKernel(moving, ctrl_pts) basis[:, 4:] = U * ml.mat(trans) #print npy.array(basis) T = basis * ml.mat(para) T *= para2[3] T += C2 - C if (fixed_bif >= 0) and (moving_bif >= 0): T[:, 2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) M += T result_center_points = npy.array(M).copy() result_center_points[:, :3] /= fixed_res[:3] result_center_points = npy.insert(result_center_points, [result_center_points.shape[1]], moving_points[:, -1].reshape(-1, 1), axis=1) result_center_points = npy.append(result_center_points, npy.array([[-1, -1, -1, -1]]), axis=0) #print result_center_points moving = ctrl_pts_backup.copy() m = moving.shape[0] M = ml.mat(moving.copy()) C = npy.asmatrix(para2[:3]) C = ml.repmat(C, m, 1) moving -= C moving /= para2[3] C2 = npy.asmatrix(para2[4:7]) C2 = ml.repmat(C2, m, 1) basis = ml.zeros([m, n], dtype=npy.float32) basis[:, 0] = 1 basis[:, 1:4] = moving U = gutil.ComputeTPSKernel(moving, ctrl_pts) basis[:, 4:] = U * ml.mat(trans) #print npy.array(basis) T = basis * ml.mat(para) T *= para2[3] T += C2 - C if (fixed_bif >= 0) and (moving_bif >= 0): T[:, 2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) M += T result_ctrl = npy.array(M).copy() #print result_ctrl image_type = fixedData.getITKImageType() transform_type = itk.ThinPlateSplineKernelTransform.D3 transform = transform_type.New() pointset_type = itk.PointSet.PD33S source_pointset = pointset_type.New() target_pointset = pointset_type.New() count = 0 for point in ctrl_pts_backup: tmp_point = itk.Point.D3() tmp_point[0] = point[0] tmp_point[1] = point[1] tmp_point[2] = point[2] source_pointset.SetPoint(count, tmp_point) count += 1 count = 0 for point in ctrl_pts_backup: tmp_point = itk.Point.D3() tmp_point[0] = point[0] tmp_point[1] = point[1] tmp_point[2] = point[2] target_pointset.SetPoint(count, tmp_point) count += 1 transform.SetSourceLandmarks(source_pointset) transform.SetTargetLandmarks(target_pointset) transform.ComputeWMatrix() """ # Test for TPS Transform moving_points = movingData.getPointSet('Centerline').copy() moving_points = moving_points[npy.where(moving_points[:, 0] >= 0)] moving = moving_points[:, :3].copy() moving *= moving_res[:3] for point in moving: tmp_point = itk.Point.D3() tmp_point[0] = point[0] tmp_point[1] = point[1] tmp_point[2] = point[2] rst_point = transform.TransformPoint(tmp_point) point[0] = rst_point[0] point[1] = rst_point[1] point[2] = rst_point[2] moving /= fixed_res[:3] print moving """ # image_type = fixedData.getITKImageType() # resampler = itk.ResampleImageFilter[image_type, image_type].New() # movingImage = movingData.getITKImage() # fixedImage = fixedData.getITKImage() # # resampler.SetTransform(transform) # resampler.SetInput(movingImage) # # region = fixedImage.GetLargestPossibleRegion() # # resampler.SetSize(region.GetSize()) # resampler.SetOutputSpacing(fixedImage.GetSpacing()) # resampler.SetOutputDirection(fixedImage.GetDirection()) # resampler.SetOutputOrigin(fixedImage.GetOrigin()) # resampler.SetDefaultPixelValue(0) # resampler.Update() # # outputImage = resampler.GetOutput() # image = itk.PyBuffer[image_type].GetArrayFromImage(outputImage) if isTime: return movingData.getData().copy(), { 'Contour': new_trans_points, 'Centerline': result_center_points }, [0, 0, 0], time2 - time1 return movingData.getData().copy(), { 'Contour': new_trans_points, 'Centerline': result_center_points }, [0, 0, 0]
def process(self, dataset, i): # ICP with centerline print 'Register Data %s with ICP...' % self.ini.file.name_result[i] tmp = dataset['mov'].pointSet.data['Contour'].copy() for sd in range(0, 16): mean_dis_all = npy.zeros([4, 3], dtype=npy.float32) mean_whole_all = npy.zeros([4, 1], dtype=npy.float32) if sd > 0: repeat = self.repeat else: repeat = 1 for i in range(repeat): dataset['mov'].pointSet.data['Contour'] = AddNoise( tmp, float(sd) / 5) dataset['mov'].pointSet.data[ 'Centerline'] = calCenterlineFromContour( dataset['mov'].pointSet.data) # Centerline label data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1) resultData = db.ResultData( data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) mean_dis_all[0, :] += mean_dis mean_whole_all[0] += mean_whole del data, point, resultData, para # Contour label data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 0, op=True) resultData = db.ResultData( data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) mean_dis_all[1, :] += mean_dis mean_whole_all[1] += mean_whole del data, point, resultData, para # Centerline no-label data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1, op=True) resultData = db.ResultData( data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) mean_dis_all[2, :] += mean_dis mean_whole_all[2] += mean_whole del data, point, resultData, para # Contour no-label data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 0) resultData = db.ResultData( data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) mean_dis_all[3, :] += mean_dis mean_whole_all[3] += mean_whole del data, point, resultData, para sys.stdout.write(str(i) + ',') sys.stdout.flush() mean_dis_all /= repeat mean_whole_all /= repeat print ' ' print 'Noise level %fmm Done!' % (float(sd) / 5) print 'Contour Error Done! Whole mean is %0.2fmm vs %0.2fmm.' % ( mean_whole_all[0], mean_whole_all[1]) for i in range(4): self.error[i, sd, :3] += mean_dis_all[i, :] self.error[i, sd, 3] += mean_whole_all[i]
def register(self, fixedData, movingData, index=-1, discard=False, delta=0, fov=9999999.0, down_fix=1, down_mov=1, occ=9999999.0, useMask=False, isTime=False, MaxRate=0.2, aug=False, distance_fix=0.3, distance_mov=0.1, w_wrong=1.5): time1 = time.time() if index == -1: index = self.gui.getDataIndex({ 'Contour': 0, 'Centerline': 1 }, 'Select the object') if index is None: return None, None, None if index == 0: fixed_points = fixedData.getPointSet('Contour').copy() moving_points = movingData.getPointSet('Contour').copy() else: fixed_points = fixedData.getPointSet('Centerline').copy() moving_points = movingData.getPointSet('Centerline').copy() fixed_bif = db.getBifurcation(fixed_points) moving_bif = db.getBifurcation(moving_points) if useMask: mask_points = movingData.getPointSet('Mask') for point in mask_points: moving_points = npy.delete( moving_points, npy.where( (npy.abs(moving_points[:, 2] - point[2]) < 0.0001) & (npy.round(moving_points[:, -1]) == point[3])), axis=0) fixed_res = fixedData.getResolution().tolist() moving_res = movingData.getResolution().tolist() fixed_points = fixed_points[npy.where(fixed_points[:, 0] >= 0)] moving_points = moving_points[npy.where(moving_points[:, 0] >= 0)] # Use the bifurcation as the initial position if (fixed_bif < 0) or (moving_bif < 0): fixed_min = 0 # Augmentation of pointset fixed = fixed_points.copy() moving = moving_points.copy() if index == 1 and aug: fixed = util.augmentCenterline(fixed, 1, 10) moving = util.augmentCenterline(moving, 1, 10) fix_dis = util.getAxisSin(fixed, 3 / fixed_res[2]) * distance_fix mov_dis = util.getAxisSin(moving, 3 / moving_res[2]) * distance_mov fixed = util.resampleCenterline(fixed, fix_dis / fixed_res[2]) moving = util.resampleCenterline(moving, mov_dis / moving_res[2]) fixed = fixed[npy.cast[npy.int32](npy.abs(fixed[:, 2] - fixed_bif)) % down_fix == 0] moving = moving[npy.cast[npy.int32](npy.abs(moving[:, 2] - moving_bif)) % down_mov == 0] fixed[:, :3] *= fixed_res[:3] moving[:, :3] *= moving_res[:3] if (fixed_bif >= 0) and (moving_bif >= 0): fixed[:, 2] -= (fixed_bif * fixed_res[2] - moving_bif * moving_res[2] + delta) # Prepare for ICP LandmarkTransform = vtk.vtkLandmarkTransform() LandmarkTransform.SetModeToRigidBody() MaxIterNum = 50 #MaxNum = 600 MaxNum = int(MaxRate * moving.shape[0] + 0.5) targetPoints = [vtk.vtkPoints(), vtk.vtkPoints(), vtk.vtkPoints()] targetVertices = [ vtk.vtkCellArray(), vtk.vtkCellArray(), vtk.vtkCellArray() ] target = [vtk.vtkPolyData(), vtk.vtkPolyData(), vtk.vtkPolyData()] Locator = [ vtk.vtkCellLocator(), vtk.vtkCellLocator(), vtk.vtkCellLocator() ] for i in range(3): for x in fixed[npy.round(fixed[:, 3]) == i]: id = targetPoints[i].InsertNextPoint(x[0], x[1], x[2]) targetVertices[i].InsertNextCell(1) targetVertices[i].InsertCellPoint(id) target[i].SetPoints(targetPoints[i]) target[i].SetVerts(targetVertices[i]) Locator[i].SetDataSet(target[i]) Locator[i].SetNumberOfCellsPerBucket(1) Locator[i].BuildLocator() step = 1 if moving.shape[0] > MaxNum: ind = moving[:, 2].argsort() moving = moving[ind, :] step = moving.shape[0] / MaxNum nb_points = moving.shape[0] / step accumulate = vtk.vtkTransform() accumulate.PostMultiply() points1 = vtk.vtkPoints() points1.SetNumberOfPoints(nb_points) label = npy.zeros([MaxNum * 2], dtype=npy.int8) j = 0 for i in range(nb_points): points1.SetPoint(i, moving[j][0], moving[j][1], moving[j][2]) label[i] = moving[j][3] j += step closestp = vtk.vtkPoints() closestp.SetNumberOfPoints(nb_points) points2 = vtk.vtkPoints() points2.SetNumberOfPoints(nb_points) id1 = id2 = vtk.mutable(0) dist = vtk.mutable(0.0) outPoint = [0.0, 0.0, 0.0] p1 = [0.0, 0.0, 0.0] p2 = [0.0, 0.0, 0.0] iternum = 0 a = points1 b = points2 w_mat = [[1, w_wrong, w_wrong], [w_wrong, 1, 99999999], [w_wrong, 99999999, 1]] while True: for i in range(nb_points): min_dist = 99999999 min_outPoint = [0.0, 0.0, 0.0] for j in range(3): Locator[j].FindClosestPoint(a.GetPoint(i), outPoint, id1, id2, dist) dis = npy.sqrt( npy.sum((npy.array(outPoint) - a.GetPoint(i))**2)) if dis * w_mat[label[i]][j] < min_dist: min_dist = dis * w_mat[label[i]][j] min_outPoint = copy.deepcopy(outPoint) closestp.SetPoint(i, min_outPoint) LandmarkTransform.SetSourceLandmarks(a) LandmarkTransform.SetTargetLandmarks(closestp) LandmarkTransform.Update() accumulate.Concatenate(LandmarkTransform.GetMatrix()) iternum += 1 if iternum >= MaxIterNum: break for i in range(nb_points): a.GetPoint(i, p1) LandmarkTransform.InternalTransformPoint(p1, p2) b.SetPoint(i, p2) b, a = a, b time2 = time.time() # Get the result transformation parameters matrix = accumulate.GetMatrix() T = ml.mat([ matrix.GetElement(0, 3), matrix.GetElement(1, 3), matrix.GetElement(2, 3) ]).T R = ml.mat([[ matrix.GetElement(0, 0), matrix.GetElement(0, 1), matrix.GetElement(0, 2) ], [ matrix.GetElement(1, 0), matrix.GetElement(1, 1), matrix.GetElement(1, 2) ], [ matrix.GetElement(2, 0), matrix.GetElement(2, 1), matrix.GetElement(2, 2) ]]).I if (fixed_bif >= 0) and (moving_bif >= 0): T[2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2] + delta) # Resample the moving contour moving_points = movingData.getPointSet('Contour').copy() moving_center = movingData.getPointSet('Centerline').copy() new_trans_points, result_center_points = moving_points, moving_center result_center_points[:, :3] = util.applyTransformForPoints( result_center_points[:, :3], moving_res, fixed_res, R, T, ml.zeros([3, 1], dtype=npy.float32)) new_trans_points[:, :3] = util.applyTransformForPoints( new_trans_points[:, :3], moving_res, fixed_res, R, T, ml.zeros([3, 1], dtype=npy.float32)) T = -T T = R * T transform = sitk.Transform(3, sitk.sitkAffine) para = R.reshape(1, -1).tolist()[0] + T.T.tolist()[0] transform.SetParameters(para) movingImage = movingData.getSimpleITKImage() fixedImage = fixedData.getSimpleITKImage() resultImage = sitk.Resample(movingImage, fixedImage, transform, sitk.sitkLinear, 0, sitk.sitkFloat32) if isTime: return sitk.GetArrayFromImage(resultImage), { 'Contour': new_trans_points, 'Centerline': result_center_points }, para + [0, 0, 0], time2 - time1 return sitk.GetArrayFromImage(resultImage), { 'Contour': new_trans_points, 'Centerline': result_center_points }, para + [0, 0, 0]
def register(self, fixedData, movingData, index = -1, discard = False, delta = 0, fov = 9999999.0, down_fix = 1, down_mov = 1, occ = 9999999.0, op = False, useMask = False, isTime = False, MaxRate = 0.2, aug = False, distance_fix = 0.3, distance_mov = 0.1, w_wrong = 1.5, truth_mov = None): time1 = time.time() if index == -1: index = self.gui.getDataIndex({'Contour': 0, 'Centerline': 1}, 'Select the object') if index is None: return None, None, None if index == 0: fixed_points = fixedData.getPointSet('Contour').copy() moving_points = movingData.getPointSet('Contour').copy() else: fixed_points = fixedData.getPointSet('Centerline').copy() moving_points = movingData.getPointSet('Centerline').copy() if truth_mov is None: truth_mov = moving_points.copy() fixed_bif = db.getBifurcation(fixed_points) moving_bif = db.getBifurcation(moving_points) if useMask: mask_points = movingData.getPointSet('Mask') for point in mask_points: moving_points = npy.delete(moving_points, npy.where((npy.abs(moving_points[:, 2] - point[2]) < 0.0001) & (npy.round(moving_points[:, -1]) == point[3])), axis = 0) fixed_res = fixedData.getResolution().tolist() moving_res = movingData.getResolution().tolist() fixed_points = fixed_points[npy.where(fixed_points[:, 0] >= 0)] moving_points = moving_points[npy.where(moving_points[:, 0] >= 0)] # Use the bifurcation as the initial position if (fixed_bif < 0) or (moving_bif < 0): fixed_min = 0 # Augmentation of pointset fixed = fixed_points.copy() moving = moving_points.copy() if index == 1 and aug: fixed = util.augmentCenterline(fixed, 1, 10) moving = util.augmentCenterline(moving, 1, 10) fix_dis = util.getAxisSin(fixed, 3 / fixed_res[2]) * distance_fix mov_dis = util.getAxisSin(moving, 3 / moving_res[2]) * distance_mov fixed = util.resampleCenterline(fixed, fix_dis / fixed_res[2]) moving = util.resampleCenterline(moving, mov_dis / moving_res[2]) fixed = fixed[npy.cast[npy.int32](npy.abs(fixed[:, 2] - fixed_bif)) % down_fix == 0] moving = moving[npy.cast[npy.int32](npy.abs(moving[:, 2] - moving_bif)) % down_mov == 0] fixed[:, :3] *= fixed_res[:3] moving[:, :3] *= moving_res[:3] new_trans_points = truth_mov result_center_points = movingData.getPointSet('Centerline').copy() new_trans_points = new_trans_points[new_trans_points[:, 3] >= 0] result_center_points = result_center_points[result_center_points[:, 3] >= 0] new_trans_points[:, :3] *= moving_res[:3] result_center_points[:, :3] *= moving_res[:3] if (fixed_bif >= 0) and (moving_bif >= 0): fixed[:, 2] -= (fixed_bif * fixed_res[2] - moving_bif * moving_res[2] + delta) # Prepare for ICP MaxIterNum = 50 #MaxNum = 600 MaxNum = int(MaxRate * moving.shape[0] + 0.5) targetPoints = [vtk.vtkPoints(), vtk.vtkPoints(), vtk.vtkPoints()] targetVertices = [vtk.vtkCellArray(), vtk.vtkCellArray(), vtk.vtkCellArray()] target = [vtk.vtkPolyData(), vtk.vtkPolyData(), vtk.vtkPolyData()] Locator = [vtk.vtkCellLocator(), vtk.vtkCellLocator(), vtk.vtkCellLocator()] for i in range(3): for x in fixed[npy.round(fixed[:, 3]) == i]: id = targetPoints[i].InsertNextPoint(x[0], x[1], x[2]) targetVertices[i].InsertNextCell(1) targetVertices[i].InsertCellPoint(id) target[i].SetPoints(targetPoints[i]) target[i].SetVerts(targetVertices[i]) Locator[i].SetDataSet(target[i]) Locator[i].SetNumberOfCellsPerBucket(1) Locator[i].BuildLocator() step = 1 if moving.shape[0] > MaxNum: ind = moving[:, 2].argsort() moving = moving[ind, :] step = moving.shape[0] / MaxNum nb_points = moving.shape[0] / step points1 = vtk.vtkPoints() points1.SetNumberOfPoints(nb_points) label = npy.zeros([MaxNum * 2], dtype = npy.int8) j = 0 for i in range(nb_points): points1.SetPoint(i, moving[j][0], moving[j][1], moving[j][2]) label[i] = moving[j][3] j += step closestp = vtk.vtkPoints() closestp.SetNumberOfPoints(nb_points) points2 = vtk.vtkPoints() points2.SetNumberOfPoints(nb_points) id1 = id2 = vtk.mutable(0) dist = vtk.mutable(0.0) outPoint = [0.0, 0.0, 0.0] p1 = [0.0, 0.0, 0.0] p2 = [0.0, 0.0, 0.0] iternum = 0 a = points1 b = points2 if (op and index == 0) or (not op and index == 1): w_mat = [[1, w_wrong, w_wrong], [w_wrong, 1, 99999999], [w_wrong, 99999999, 1]] else: w_mat = [[1, 1, 1], [1, 1, 1], [1, 1, 1]] accumulate = vtk.vtkTransform() accumulate.PostMultiply() LandmarkTransform = vtk.vtkLandmarkTransform() LandmarkTransform.SetModeToRigidBody() while True: for i in range(nb_points): min_dist = 99999999 min_outPoint = [0.0, 0.0, 0.0] for j in range(3): Locator[j].FindClosestPoint(a.GetPoint(i), outPoint, id1, id2, dist) dis = npy.sqrt(npy.sum((npy.array(outPoint) - a.GetPoint(i)) ** 2)) if dis * w_mat[label[i]][j] < min_dist: min_dist = dis * w_mat[label[i]][j] min_outPoint = copy.deepcopy(outPoint) closestp.SetPoint(i, min_outPoint) LandmarkTransform.SetSourceLandmarks(a) LandmarkTransform.SetTargetLandmarks(closestp) LandmarkTransform.Update() accumulate.Concatenate(LandmarkTransform.GetMatrix()) iternum += 1 for i in range(nb_points): a.GetPoint(i, p1) LandmarkTransform.InternalTransformPoint(p1, p2) b.SetPoint(i, p2) b, a = a, b if iternum >= MaxIterNum: break matrix = accumulate.GetMatrix() T = ml.mat([matrix.GetElement(0, 3), matrix.GetElement(1, 3), matrix.GetElement(2, 3)]).T R = ml.mat([[matrix.GetElement(0, 0), matrix.GetElement(0, 1), matrix.GetElement(0, 2)], [matrix.GetElement(1, 0), matrix.GetElement(1, 1), matrix.GetElement(1, 2)], [matrix.GetElement(2, 0), matrix.GetElement(2, 1), matrix.GetElement(2, 2)]]).I result_center_points[:, :3] = util.applyTransformForPoints(result_center_points[:, :3], npy.array([1.0, 1, 1]), npy.array([1.0, 1, 1]), R, T, ml.zeros([3, 1], dtype = npy.float32)) new_trans_points[:, :3] = util.applyTransformForPoints(new_trans_points[:, :3], npy.array([1.0, 1, 1]), npy.array([1.0, 1, 1]), R, T, ml.zeros([3, 1], dtype = npy.float32)) LandmarkTransform = vtk.vtkThinPlateSplineTransform() LandmarkTransform.SetBasisToR() iternum = 0 # Non-rigid while True: for i in range(nb_points): min_dist = 99999999 min_outPoint = [0.0, 0.0, 0.0] for j in range(3): Locator[j].FindClosestPoint(a.GetPoint(i), outPoint, id1, id2, dist) dis = npy.sqrt(npy.sum((npy.array(outPoint) - a.GetPoint(i)) ** 2)) if dis * w_mat[label[i]][j] < min_dist: min_dist = dis * w_mat[label[i]][j] min_outPoint = copy.deepcopy(outPoint) closestp.SetPoint(i, min_outPoint) LandmarkTransform.SetSourceLandmarks(a) LandmarkTransform.SetTargetLandmarks(closestp) LandmarkTransform.Update() ''' for i in range(result_center_points.shape[0]): LandmarkTransform.InternalTransformPoint([result_center_points[i, 0], result_center_points[i, 1], result_center_points[i, 2]], p2) result_center_points[i, :3] = p2 ''' for i in range(new_trans_points.shape[0]): LandmarkTransform.InternalTransformPoint([new_trans_points[i, 0], new_trans_points[i, 1], new_trans_points[i, 2]], p2) new_trans_points[i, :3] = p2 iternum += 1 if iternum >= 1: break for i in range(nb_points): a.GetPoint(i, p1) LandmarkTransform.InternalTransformPoint(p1, p2) b.SetPoint(i, p2) b, a = a, b time2 = time.time() if (fixed_bif >= 0) and (moving_bif >= 0): new_trans_points[:, 2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2] + delta) result_center_points[:, 2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2] + delta) new_trans_points[:, :3] /= fixed_res[:3] result_center_points[:, :3] /= fixed_res[:3] resultImage = movingData.getData().copy() sa = SurfaceErrorAnalysis(None) dataset = db.BasicData(npy.array([[[0]]]), fixedData.getInfo(), {'Contour': new_trans_points, 'Centerline': result_center_points}) mean_dis, mean_whole, max_dis, max_whole = sa.analysis(dataset, point_data_fix = fixedData.getPointSet('Contour').copy(), useResult = True) del dataset print mean_dis print mean_whole if isTime: return resultImage, {'Contour': new_trans_points, 'Centerline': result_center_points}, [mean_dis, mean_whole], time2 - time1 return resultImage, {'Contour': new_trans_points, 'Centerline': result_center_points}, [mean_dis, mean_whole]
def analysis(self, data, point_data_fix = None, all = False): if point_data_fix is None: point_data_fix = self.gui.dataModel[data.getFixedIndex()].getPointSet('Contour').copy() point_data_result = data.getPointSet('Contour').copy() self.spacing = data.getResolution().tolist() self.spacing[2] = 1.0 # The resolution of z axis is nothing to do with the analysis point_data_fix[:, :3] *= self.spacing[:3] point_data_result[:, :3] *= self.spacing[:3] cnt_num = npy.array([0, 0, 0]) mean_dis = npy.array([0.0, 0.0, 0.0]) max_dis = npy.array([0.0, 0.0, 0.0]) square_sum_dis = npy.array([0.0, 0.0, 0.0]) if all: result = [{}, {}, {}] bif = db.getBifurcation(point_data_fix) for cnt in range(3): temp_result = point_data_result[npy.where(npy.round(point_data_result[:, -1]) == cnt)] temp_fix = point_data_fix[npy.where(npy.round(point_data_fix[:, -1]) == cnt)] if not temp_result.shape[0] or not temp_fix.shape[0]: continue zmin = int(npy.max([npy.min(temp_result[:, 2]), npy.min(temp_fix[:, 2])]) + 0.5) zmax = int(npy.min([npy.max(temp_result[:, 2]), npy.max(temp_fix[:, 2])]) + 0.5) for z in range(zmin, zmax + 1): data_fix = temp_fix[npy.where(npy.round(temp_fix[:, 2]) == z)] data_result = temp_result[npy.where(npy.round(temp_result[:, 2]) == z)] if data_fix is not None and data_result is not None: if data_fix.shape[0] == 0 or data_result.shape[0] == 0: continue cnt_num[cnt] += 1 #center_fix = npy.mean(data_fix[:, :2], axis = 0) center_fix = calCentroidFromContour(data_fix[:, :2])[0] #center_result = npy.mean(data_result[:, :2], axis = 0) center_result = calCentroidFromContour(data_result[:, :2])[0] points_fix = getPointsOntheSpline(data_fix, center_fix, 900) points_result = getPointsOntheSpline(data_result, center_result, 900) i = j = 0 for k in range(-44, 46): angle = k * 4 / 180.0 * npy.pi while i < 900 and points_fix[i, 2] < angle: i += 1 if i == 900 or (i > 0 and angle - points_fix[i - 1, 2] < points_fix[i, 2] - angle): ind_fix = i - 1 else: ind_fix = i while j < 900 and points_result[j, 2] < angle: j += 1 if j == 900 or (j > 0 and angle - points_result[j - 1, 2] < points_result[j, 2] - angle): ind_result = j - 1 else: ind_result = j temp_dis = npy.hypot(points_fix[ind_fix, 0] - points_result[ind_result, 0], points_fix[ind_fix, 1] - points_result[ind_result, 1]) max_dis[cnt] = npy.max([max_dis[cnt], temp_dis]) mean_dis[cnt] += temp_dis square_sum_dis[cnt] += temp_dis ** 2 if all: result[cnt][z - bif] = result[cnt].get(z - bif, 0) + temp_dis cnt_total = npy.sum(cnt_num) sd = npy.sqrt(npy.max([(square_sum_dis - mean_dis ** 2 / (90 * cnt_num)) / (90 * cnt_num - 1), [0, 0, 0]], axis = 0)) sd[sd != sd] = 0 sd_all = npy.sqrt(npy.max([(npy.sum(square_sum_dis) - npy.sum(mean_dis) ** 2 / (90 * cnt_total)) / (90 * cnt_total - 1), 0])) mean_dis /= 90 mean_whole = npy.sum(mean_dis) mean_dis /= cnt_num mean_dis[mean_dis != mean_dis] = 0 # Replace the NAN in the mean distance if self.gui is not None: message = "Error on Vessel 0: %0.2fmm (SD = %0.2fmm, Total %d slices)\nError on Vessel 1: %0.2fmm (SD = %0.2fmm, Total %d slices)\nError on Vessel 2: %0.2fmm (SD = %0.2fmm, Total %d slices)\nWhole Error: %0.2fmm (SD = %0.2fmm, Total %d slices)\n" \ % (mean_dis[0], sd[0], cnt_num[0], mean_dis[1], sd[1], cnt_num[1], mean_dis[2], sd[2], cnt_num[2], mean_whole / cnt_total, sd_all, cnt_total) + \ "-----------------------------------------------------------------------------\n" + \ "Max Error on Vessel 0: %0.2fmm\nMax Error on Vessel 1: %0.2fmm\nMax Error on Vessel 2: %0.2fmm\nTotal Max Error: %0.2fmm" \ % (max_dis[0], max_dis[1], max_dis[2], npy.max(max_dis)); self.gui.showErrorMessage("Contour Registration Error", message) if not all: return mean_dis, mean_whole / cnt_total, max_dis, npy.max(max_dis) else: for cnt in range(3): for x in result[cnt].keys(): result[cnt][x] /= 90 return mean_dis, mean_whole / cnt_total, max_dis, npy.max(max_dis), result
def writeImageFile(image, file_name): data_model = [image] db.saveRawData(get_exe_path() + "/" + file_name, data_model, 0) del data_model
def readImageFile(file_name): image, info, point = db.loadRawData(get_exe_path() + "/" + file_name) return image
def process(self, dataset, i): def autoDetectContour(point, cnt, start, end, delta, res): self.new_points = npy.append(self.new_points, point, 0) points = point[:, :-2] d = 20 count = 0 for i in range(start + delta, end + delta, delta): center = calCentroidFromContour(points).reshape(2) image = dataset['fix'].getData()[i, :, :].transpose().copy() image = (image - npy.min(image)) / (npy.max(image) - npy.min(image)) * 255 down = npy.max([npy.ceil(center[0] - d / res[0]), 0]) up = npy.min([npy.floor(center[0] + d / res[0]), image.shape[0]]) left = npy.max([npy.ceil(center[1] - d / res[1]), 0]) right = npy.min([npy.floor(center[1] + d / res[1]), image.shape[1]]) crop_image = image[down : up, left : right] center -= [down, left] result = ac_segmentation(center, crop_image) a1 = ac_area(points.transpose(), image.shape) a2 = ac_area(result, crop_image.shape) rate = a2 * 1.0 / a1 if rate >= min(1.5 + count * 0.2, 2.1) or rate <= 0.7: temp_array = points.copy() if cnt != 1 and rate > 0.7: count += 1 else: temp_array = result.transpose().copy() temp_array[:, :2] += [down, left] count = 0 points = temp_array.copy() temp_array = npy.insert(temp_array, 2, [[i], [cnt]], 1) self.new_points = npy.append(self.new_points, temp_array, 0) sys.stdout.write(str(i) + ',') sys.stdout.flush() print ' ' # Segmentation of data print 'Segment Data %s...' % self.ini.file.name_result[i] tmp = dataset['fix'].pointSet.data['Contour'] tmp = tmp[tmp[:, 0] >= 0] self.new_points = npy.array([[-1, -1, -1, -1]], dtype = npy.float32) time1 = time.time() bottom = int(npy.round(npy.min(tmp[:, 2]))) bif = int(db.getBifurcation(tmp) + 0.5) up = int(npy.round(npy.max(tmp[:, 2]))) point_vital = [0] * 3 point_vital[0] = tmp[(npy.round(tmp[:, -1]) == 0) & (npy.round(tmp[:, 2]) == bottom)].copy() point_vital[1] = tmp[(npy.round(tmp[:, -1]) == 1) & (npy.round(tmp[:, 2]) == up)].copy() point_vital[2] = tmp[(npy.round(tmp[:, -1]) == 2) & (npy.round(tmp[:, 2]) == up)].copy() autoDetectContour(point_vital[0], 0, bottom, bif, 1, dataset['fix'].getResolution().tolist()) autoDetectContour(point_vital[1], 1, up, bif, -1, dataset['fix'].getResolution().tolist()) autoDetectContour(point_vital[2], 2, up, bif, -1, dataset['fix'].getResolution().tolist()) print ' ' print 'Finish segmentation of MR. ' true_fixed_points = dataset['fix'].pointSet.data['Contour'].copy() dataset['fix'].pointSet.data['Contour'] = self.new_points dataset['fix'].pointSet.data['Centerline'] = calCenterlineFromContour(dataset['fix'].pointSet.data) hybrid = NonrigidHybridRegistration(None) print 'Register Data %s with Hybrid Method...' % (self.ini.file.name_result[i]) data, point, para = hybrid.register(dataset['fix'], dataset['mov'], regPara = self.regPara, true_fixed_points = true_fixed_points) print 'Done!' for k in range(len(self.regPara)): self.sheet1.write(k + 1, i + 2, float(para[k, 0])) self.sheet2.write(k + 1, i + 2, float(para[k, 1])) self.sheet3.write(k + 1, i + 2, float(para[k, 2])) self.sheet1.write(0, i + 2, self.ini.file.name_result[i]) self.sheet2.write(0, i + 2, self.ini.file.name_result[i]) self.sheet3.write(0, i + 2, self.ini.file.name_result[i]) self.book.save(self.path + self.ini.file.savedir + 'nonrigid' + str(self.first) + '.xls') del para del hybrid del true_fixed_points
def analysis(self, data, point_data_fix = None, area = False): if point_data_fix is None: point_data_fix = self.gui.dataModel[data.getFixedIndex()].getPointSet('Contour').copy() point_data_result = data.getPointSet('Contour').copy() self.spacing = data.getResolution().tolist() point_data_fix[:, :2] *= self.spacing[:2] point_data_result[:, :2] *= self.spacing[:2] center_data = calCenterlineFromContour({'Contour': point_data_fix}) ind = center_data[:, 2].argsort() center_data = center_data[ind] center_data_z = center_data[:, 2].copy() fixed_bif = db.getBifurcation(center_data) bif_point = center_data[npy.round(center_data[:, 2]) == fixed_bif - 1] center_data[:, :3] *= self.spacing[:3] bif_point[:, :3] *= self.spacing[:3] spline = [None, None, None] for cnt in range(3): spline[cnt] = [None, None, None] xx = center_data_z[npy.round(center_data[:, -1]) == cnt] yy = center_data[npy.round(center_data[:, -1]) == cnt] if cnt > 0: xx = npy.append(fixed_bif - 1, xx) yy = npy.append(bif_point, yy, axis = 0) for i in range(3): spline[cnt][i] = itp.InterpolatedUnivariateSpline(xx, yy[:, i]) cnt_num = npy.array([0, 0, 0]) mean_dis = npy.array([0.0, 0.0, 0.0]) max_dis = npy.array([0.0, 0.0, 0.0]) square_sum_dis = npy.array([0.0, 0.0, 0.0]) if area: area_mr = npy.array([0.0, 0.0, 0.0]) area_us = npy.array([0.0, 0.0, 0.0]) for cnt in range(3): temp_result = point_data_result[npy.where(npy.round(point_data_result[:, -1]) == cnt)] temp_fix = point_data_fix[npy.where(npy.round(point_data_fix[:, -1]) == cnt)] if not temp_result.shape[0] or not temp_fix.shape[0]: continue zmin = int(npy.max([npy.min(temp_result[:, 2]), npy.min(temp_fix[:, 2])]) + 0.5) zmax = int(npy.min([npy.max(temp_result[:, 2]), npy.max(temp_fix[:, 2])]) + 0.5) for z in range(zmin, zmax + 1): data_fix = temp_fix[npy.where(npy.round(temp_fix[:, 2]) == z)] data_result = temp_result[npy.where(npy.round(temp_result[:, 2]) == z)] if data_fix is not None and data_result is not None: if data_fix.shape[0] == 0 or data_result.shape[0] == 0: continue cnt_num[cnt] += 1 #center_fix = npy.mean(data_fix[:, :2], axis = 0) center_fix, area_fix = calCentroidFromContour(data_fix[:, :2], True) center_fix = center_fix[0] #center_result = npy.mean(data_result[:, :2], axis = 0) center_result, area_result = calCentroidFromContour(data_result[:, :2], True) center_result = center_result[0] if area: area_mr[cnt] += area_fix area_us[cnt] += area_result points_fix = getPointsOntheSpline(data_fix, center_fix, 900) points_result = getPointsOntheSpline(data_result, center_result, 900) normal = npy.array([None, None, None]) for i in range(3): normal[i] = spline[cnt][i].derivatives(z)[1] w1 = normal[2] ** 2 / npy.sum(normal ** 2) # cos(alpha) ^ 2 theta0 = npy.arctan2(normal[1], normal[0]) i = j = 0 for k in range(-44, 46): angle = k * 4 / 180.0 * npy.pi while i < 900 and points_fix[i, 2] < angle: i += 1 if i == 900 or (i > 0 and angle - points_fix[i - 1, 2] < points_fix[i, 2] - angle): ind_fix = i - 1 else: ind_fix = i while j < 900 and points_result[j, 2] < angle: j += 1 if j == 900 or (j > 0 and angle - points_result[j - 1, 2] < points_result[j, 2] - angle): ind_result = j - 1 else: ind_result = j weigh = npy.sqrt(npy.sin(angle - theta0) ** 2 + npy.cos(angle - theta0) ** 2 / w1) temp_dis = npy.hypot(points_fix[ind_fix, 0] - points_result[ind_result, 0], points_fix[ind_fix, 1] - points_result[ind_result, 1]) / weigh #if area: # temp_dis /= max([area_result / area_fix, area_fix / area_result]) max_dis[cnt] = npy.max([max_dis[cnt], temp_dis]) mean_dis[cnt] += temp_dis cnt_total = npy.sum(cnt_num) mean_dis /= 90 if area: for cnt in range(3): if area_mr[cnt] < area_us[cnt]: rate = area_us[cnt] / area_mr[cnt] else: rate = area_us[cnt] / area_mr[cnt] mean_dis[cnt] /= rate mean_whole = npy.sum(mean_dis) mean_dis /= cnt_num mean_dis[mean_dis != mean_dis] = 0 # Replace the NAN in the mean distance if self.gui is not None: message = "Error on Vessel 0: %0.2fmm (Total %d slices)\nError on Vessel 1: %0.2fmm (Total %d slices)\nError on Vessel 2: %0.2fmm (Total %d slices)\nWhole Error: %0.2fmm (Total %d slices)\n" \ % (mean_dis[0], cnt_num[0], mean_dis[1], cnt_num[1], mean_dis[2], cnt_num[2], mean_whole / cnt_total, cnt_total) + \ "-----------------------------------------------------------------------------\n" + \ "Max Error on Vessel 0: %0.2fmm\nMax Error on Vessel 1: %0.2fmm\nMax Error on Vessel 2: %0.2fmm\nTotal Max Error: %0.2fmm" \ % (max_dis[0], max_dis[1], max_dis[2], npy.max(max_dis)); self.gui.showErrorMessage("Weighted Contour Registration Error", message) return mean_dis, mean_whole / cnt_total, max_dis, npy.max(max_dis)
def process(self, dataset, i): # ICP with contour without label print 'Register Data %s with ICP(contour) without label...' % self.ini.file.name_result[ i] data, point, para, time = self.icp.register(dataset['fix'], dataset['mov'], 0, op=False, isTime=True) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole dice_index, dice_index_all = self.areaerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet1.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet1.write(j + 1, i + 2, mean_dis[j]) self.sheet1.write(j + 5, i + 2, max_dis[j]) self.sheet1.write(j + 9, i + 2, dice_index[j]) self.sheet1.write(4, i + 2, mean_whole) self.sheet1.write(8, i + 2, max_whole) self.sheet1.write(12, i + 2, dice_index_all) self.sheet1.write(13, i + 2, time) self.book.save(self.path + self.ini.file.savedir + 'snap_feature.xls') del data, point, resultData # ICP with centerline without label print 'Register Data %s with ICP(centerline) without label...' % self.ini.file.name_result[ i] data, point, para, time = self.icp.register(dataset['fix'], dataset['mov'], 1, op=True, isTime=True) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole dice_index, dice_index_all = self.areaerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet2.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet2.write(j + 1, i + 2, mean_dis[j]) self.sheet2.write(j + 5, i + 2, max_dis[j]) self.sheet2.write(j + 9, i + 2, dice_index[j]) self.sheet2.write(4, i + 2, mean_whole) self.sheet2.write(8, i + 2, max_whole) self.sheet2.write(12, i + 2, dice_index_all) self.sheet2.write(13, i + 2, time) self.book.save(self.path + self.ini.file.savedir + 'snap_feature.xls') del data, point, resultData # ICP with contour with label print 'Register Data %s with ICP(contour) with label...' % self.ini.file.name_result[ i] data, point, para, time = self.icp.register(dataset['fix'], dataset['mov'], 0, op=True, isTime=True) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole dice_index, dice_index_all = self.areaerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet3.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet3.write(j + 1, i + 2, mean_dis[j]) self.sheet3.write(j + 5, i + 2, max_dis[j]) self.sheet3.write(j + 9, i + 2, dice_index[j]) self.sheet3.write(4, i + 2, mean_whole) self.sheet3.write(8, i + 2, max_whole) self.sheet3.write(12, i + 2, dice_index_all) self.sheet3.write(13, i + 2, time) self.book.save(self.path + self.ini.file.savedir + 'snap_feature.xls') del data, point, resultData # ICP with centerline with label print 'Register Data %s with ICP(centerline) with label...' % self.ini.file.name_result[ i] data, point, para, time = self.icp.register(dataset['fix'], dataset['mov'], 1, op=False, isTime=True) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole dice_index, dice_index_all = self.areaerror.analysis( resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet4.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet4.write(j + 1, i + 2, mean_dis[j]) self.sheet4.write(j + 5, i + 2, max_dis[j]) self.sheet4.write(j + 9, i + 2, dice_index[j]) self.sheet4.write(4, i + 2, mean_whole) self.sheet4.write(8, i + 2, max_whole) self.sheet4.write(12, i + 2, dice_index_all) self.sheet4.write(13, i + 2, time) self.book.save(self.path + self.ini.file.savedir + 'time_feature.xls') del data, point, resultData
def analysis(self, data, point_data_fix=None, all=False): if point_data_fix is None: point_data_fix = self.gui.dataModel[ data.getFixedIndex()].getPointSet('Contour').copy() point_data_result = data.getPointSet('Contour').copy() self.spacing = data.getResolution().tolist() self.spacing[ 2] = 1.0 # The resolution of z axis is nothing to do with the analysis point_data_fix[:, :3] *= self.spacing[:3] point_data_result[:, :3] *= self.spacing[:3] cnt_num = npy.array([0, 0, 0]) mean_dis = npy.array([0.0, 0.0, 0.0]) max_dis = npy.array([0.0, 0.0, 0.0]) square_sum_dis = npy.array([0.0, 0.0, 0.0]) if all: result = [{}, {}, {}] bif = db.getBifurcation(point_data_fix) for cnt in range(3): temp_result = point_data_result[npy.where( npy.round(point_data_result[:, -1]) == cnt)] temp_fix = point_data_fix[npy.where( npy.round(point_data_fix[:, -1]) == cnt)] if not temp_result.shape[0] or not temp_fix.shape[0]: continue zmin = int( npy.max([npy.min(temp_result[:, 2]), npy.min(temp_fix[:, 2])]) + 0.5) zmax = int( npy.min([npy.max(temp_result[:, 2]), npy.max(temp_fix[:, 2])]) + 0.5) for z in range(zmin, zmax + 1): data_fix = temp_fix[npy.where(npy.round(temp_fix[:, 2]) == z)] data_result = temp_result[npy.where( npy.round(temp_result[:, 2]) == z)] if data_fix is not None and data_result is not None: if data_fix.shape[0] == 0 or data_result.shape[0] == 0: continue cnt_num[cnt] += 1 #center_fix = npy.mean(data_fix[:, :2], axis = 0) center_fix = calCentroidFromContour(data_fix[:, :2])[0] #center_result = npy.mean(data_result[:, :2], axis = 0) center_result = calCentroidFromContour( data_result[:, :2])[0] points_fix = getPointsOntheSpline(data_fix, center_fix, 900) points_result = getPointsOntheSpline( data_result, center_result, 900) i = j = 0 for k in range(-44, 46): angle = k * 4 / 180.0 * npy.pi while i < 900 and points_fix[i, 2] < angle: i += 1 if i == 900 or (i > 0 and angle - points_fix[i - 1, 2] < points_fix[i, 2] - angle): ind_fix = i - 1 else: ind_fix = i while j < 900 and points_result[j, 2] < angle: j += 1 if j == 900 or (j > 0 and angle - points_result[j - 1, 2] < points_result[j, 2] - angle): ind_result = j - 1 else: ind_result = j temp_dis = npy.hypot( points_fix[ind_fix, 0] - points_result[ind_result, 0], points_fix[ind_fix, 1] - points_result[ind_result, 1]) max_dis[cnt] = npy.max([max_dis[cnt], temp_dis]) mean_dis[cnt] += temp_dis square_sum_dis[cnt] += temp_dis**2 if all: result[cnt][z - bif] = result[cnt].get( z - bif, 0) + temp_dis cnt_total = npy.sum(cnt_num) sd = npy.sqrt( npy.max([(square_sum_dis - mean_dis**2 / (90 * cnt_num)) / (90 * cnt_num - 1), [0, 0, 0]], axis=0)) sd[sd != sd] = 0 sd_all = npy.sqrt( npy.max([(npy.sum(square_sum_dis) - npy.sum(mean_dis)**2 / (90 * cnt_total)) / (90 * cnt_total - 1), 0])) mean_dis /= 90 mean_whole = npy.sum(mean_dis) mean_dis /= cnt_num mean_dis[ mean_dis != mean_dis] = 0 # Replace the NAN in the mean distance if self.gui is not None: message = "Error on Vessel 0: %0.2fmm (SD = %0.2fmm, Total %d slices)\nError on Vessel 1: %0.2fmm (SD = %0.2fmm, Total %d slices)\nError on Vessel 2: %0.2fmm (SD = %0.2fmm, Total %d slices)\nWhole Error: %0.2fmm (SD = %0.2fmm, Total %d slices)\n" \ % (mean_dis[0], sd[0], cnt_num[0], mean_dis[1], sd[1], cnt_num[1], mean_dis[2], sd[2], cnt_num[2], mean_whole / cnt_total, sd_all, cnt_total) + \ "-----------------------------------------------------------------------------\n" + \ "Max Error on Vessel 0: %0.2fmm\nMax Error on Vessel 1: %0.2fmm\nMax Error on Vessel 2: %0.2fmm\nTotal Max Error: %0.2fmm" \ % (max_dis[0], max_dis[1], max_dis[2], npy.max(max_dis)) self.gui.showErrorMessage("Contour Registration Error", message) if not all: return mean_dis, mean_whole / cnt_total, max_dis, npy.max(max_dis) else: for cnt in range(3): for x in result[cnt].keys(): result[cnt][x] /= 90 return mean_dis, mean_whole / cnt_total, max_dis, npy.max( max_dis), result
def register(self, fixedData, movingData, index = -1, discard = False, method = "EM_TPS", execute = True, isTime = False): if index == -1: index = self.gui.getDataIndex({'Contour': 0, 'Centerline': 1}, 'Select the object') if index is None: return None, None, None if index == 0: fixed_points = fixedData.getPointSet('Contour') moving_points = movingData.getPointSet('Contour') else: fixed_points = fixedData.getPointSet('Centerline') moving_points = movingData.getPointSet('Centerline') time1 = time.time() fixed_res = fixedData.getResolution().tolist() moving_res = movingData.getResolution().tolist() fixed_points = fixed_points.copy()[npy.where(fixed_points[:, -1] >= 0)] moving_points = moving_points.copy()[npy.where(moving_points[:, -1] >= 0)] # Use the bifurcation as the initial position fixed_bif = db.getBifurcation(fixed_points) moving_bif = db.getBifurcation(moving_points) if (fixed_bif < 0) or (moving_bif < 0): fixed_min = 0 else: temp = moving_points[:, 2:] moving_delta = moving_bif - npy.min(temp[npy.where(npy.round(temp[:, 1]) == 0), 0]) #fixed_min = 0 # Augmentation of pointset fixed = fixed_points.copy() tmp_fix = fixedData.getPointSet('Centerline') tmp_fix = tmp_fix[tmp_fix[:, -1] >= 0].copy() ctrl_pts = gutil.getControlPoints(tmp_fix, 1.0 / fixed_res[2]) moving = moving_points.copy() fixed = fixed[:, :3] moving = moving[:, :3] fixed[:, :3] *= fixed_res[:3] ctrl_pts *= fixed_res[:3] ctrl_pts_backup = ctrl_pts.copy() moving[:, :3] *= moving_res[:3] if (fixed_bif >= 0) and (moving_bif >= 0): fixed[:, 2] -= (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) ctrl_pts[:, 2] -= (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) #print fixed.shape[0], moving.shape[0] eg.initial_data(fixed, moving, ctrl_pts) if execute: code = eg.run_executable(method = method) #print code if code != 0: print "GMM Fail!" return None, None, None trans, para, para2 = eg.get_final_result(methodname = method) time2 = time.time() # Clear the temp files #eg.clear_temp_file() # Get the result transformation parameters if method == 'rigid': S1 = ml.eye(3, dtype = npy.float32) * para2[3] C = npy.asmatrix(para2[:3]).T C2 = npy.asmatrix(para2[4:7]).T T0 = npy.asmatrix(para[4:]).T R = util.quaternion2rotation(para[:4]) T = S1 * T0 + C2 - C if (fixed_bif >= 0) and (moving_bif >= 0): T[2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) moving_points = movingData.getPointSet('Contour').copy() moving_center = movingData.getPointSet('Centerline').copy() #new_trans_points, result_center_points = util.resliceTheResultPoints(moving_points, moving_center, 20, moving_res, fixed_res, discard, R, T, C) new_trans_points = util.applyTransformForPoints(moving_points, moving_res, fixed_res, R, T, C) result_center_points = util.applyTransformForPoints(moving_center, moving_res, fixed_res, R, T, C) T = -T T = R * T """ # Copy the output points of GMMREG for test new_trans_points = trans if (fixed_bif >= 0) and (moving_bif >= 0): new_trans_points[:, 2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) new_trans_points[:, :3] /= fixed_res[:3] new_trans_points = npy.insert(new_trans_points, [new_trans_points.shape[1]], moving_points[:, -1].reshape(-1, 1), axis = 1) new_trans_points = npy.append(new_trans_points, npy.array([[-1, -1, -1, -1]]), axis = 0) #result_center_points = movingData.getPointSet('Centerline').copy() result_center_points = movingData.getPointSet('Contour').copy() """ transform = sitk.Transform(3, sitk.sitkAffine) para = R.reshape(1, -1).tolist()[0] + T.T.tolist()[0] transform.SetParameters(para) transform.SetFixedParameters(C.T.tolist()[0]) #movingImage = movingData.getSimpleITKImage() #fixedImage = fixedData.getSimpleITKImage() #resultImage = sitk.Resample(movingImage, fixedImage, transform, sitk.sitkLinear, 0, sitk.sitkFloat32) if isTime: #return sitk.GetArrayFromImage(resultImage), {'Contour': new_trans_points, 'Centerline': result_center_points}, para + C.T.tolist()[0], time2 - time1 return movingData.getData().copy(), {'Contour': new_trans_points, 'Centerline': result_center_points}, para + C.T.tolist()[0], time2 - time1 #return sitk.GetArrayFromImage(resultImage), {'Contour': new_trans_points, 'Centerline': result_center_points}, para + C.T.tolist()[0] return movingData.getData().copy(), {'Contour': new_trans_points, 'Centerline': result_center_points}, para + C.T.tolist()[0] else: # EM_TPS moving_points = movingData.getPointSet('Contour').copy() moving_points = moving_points[npy.where(moving_points[:, 0] >= 0)] moving = moving_points[:, :3].copy() moving *= moving_res[:3] m = moving.shape[0] n = ctrl_pts.shape[0] M = ml.mat(moving.copy()) C2 = npy.asmatrix(para2[4:7]) C2 = ml.repmat(C2, m, 1) C3 = npy.asmatrix(para2[7:]) C3 = ml.repmat(C3, n, 1) ctrl_pts -= C3 ctrl_pts /= para2[3] C = npy.asmatrix(para2[:3]) C = ml.repmat(C, m, 1) moving -= C moving /= para2[3] basis = ml.zeros([m, n], dtype = npy.float32) basis[:, 0] = 1 basis[:, 1:4] = moving U = gutil.ComputeTPSKernel(moving, ctrl_pts) basis[:, 4:] = U * ml.mat(trans) #print npy.array(basis) T = basis * ml.mat(para) T *= para2[3] T += C2 - C if (fixed_bif >= 0) and (moving_bif >= 0): T[:, 2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) M += T new_trans_points = npy.array(M).copy() new_trans_points[:, :3] /= fixed_res[:3] new_trans_points = npy.insert(new_trans_points, [new_trans_points.shape[1]], moving_points[:, -1].reshape(-1, 1), axis = 1) new_trans_points = npy.append(new_trans_points, npy.array([[-1, -1, -1, -1]]), axis = 0) moving_points = movingData.getPointSet('Centerline').copy() moving_points = moving_points[npy.where(moving_points[:, 0] >= 0)] moving = moving_points[:, :3].copy() moving *= moving_res[:3] m = moving.shape[0] M = ml.mat(moving.copy()) C2 = npy.asmatrix(para2[4:7]) C2 = ml.repmat(C2, m, 1) C = npy.asmatrix(para2[:3]) C = ml.repmat(C, m, 1) moving -= C moving /= para2[3] basis = ml.zeros([m, n], dtype = npy.float32) basis[:, 0] = 1 basis[:, 1:4] = moving U = gutil.ComputeTPSKernel(moving, ctrl_pts) basis[:, 4:] = U * ml.mat(trans) #print npy.array(basis) T = basis * ml.mat(para) T *= para2[3] T += C2 - C if (fixed_bif >= 0) and (moving_bif >= 0): T[:, 2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) M += T result_center_points = npy.array(M).copy() result_center_points[:, :3] /= fixed_res[:3] result_center_points = npy.insert(result_center_points, [result_center_points.shape[1]], moving_points[:, -1].reshape(-1, 1), axis = 1) result_center_points = npy.append(result_center_points, npy.array([[-1, -1, -1, -1]]), axis = 0) #print result_center_points moving = ctrl_pts_backup.copy() m = moving.shape[0] M = ml.mat(moving.copy()) C = npy.asmatrix(para2[:3]) C = ml.repmat(C, m, 1) moving -= C moving /= para2[3] C2 = npy.asmatrix(para2[4:7]) C2 = ml.repmat(C2, m, 1) basis = ml.zeros([m, n], dtype = npy.float32) basis[:, 0] = 1 basis[:, 1:4] = moving U = gutil.ComputeTPSKernel(moving, ctrl_pts) basis[:, 4:] = U * ml.mat(trans) #print npy.array(basis) T = basis * ml.mat(para) T *= para2[3] T += C2 - C if (fixed_bif >= 0) and (moving_bif >= 0): T[:, 2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) M += T result_ctrl = npy.array(M).copy() #print result_ctrl image_type = fixedData.getITKImageType() transform_type = itk.ThinPlateSplineKernelTransform.D3 transform = transform_type.New() pointset_type = itk.PointSet.PD33S source_pointset = pointset_type.New() target_pointset = pointset_type.New() count = 0 for point in ctrl_pts_backup: tmp_point = itk.Point.D3() tmp_point[0] = point[0] tmp_point[1] = point[1] tmp_point[2] = point[2] source_pointset.SetPoint(count, tmp_point) count += 1 count = 0 for point in ctrl_pts_backup: tmp_point = itk.Point.D3() tmp_point[0] = point[0] tmp_point[1] = point[1] tmp_point[2] = point[2] target_pointset.SetPoint(count, tmp_point) count += 1 transform.SetSourceLandmarks(source_pointset) transform.SetTargetLandmarks(target_pointset) transform.ComputeWMatrix() """ # Test for TPS Transform moving_points = movingData.getPointSet('Centerline').copy() moving_points = moving_points[npy.where(moving_points[:, 0] >= 0)] moving = moving_points[:, :3].copy() moving *= moving_res[:3] for point in moving: tmp_point = itk.Point.D3() tmp_point[0] = point[0] tmp_point[1] = point[1] tmp_point[2] = point[2] rst_point = transform.TransformPoint(tmp_point) point[0] = rst_point[0] point[1] = rst_point[1] point[2] = rst_point[2] moving /= fixed_res[:3] print moving """ # image_type = fixedData.getITKImageType() # resampler = itk.ResampleImageFilter[image_type, image_type].New() # movingImage = movingData.getITKImage() # fixedImage = fixedData.getITKImage() # # resampler.SetTransform(transform) # resampler.SetInput(movingImage) # # region = fixedImage.GetLargestPossibleRegion() # # resampler.SetSize(region.GetSize()) # resampler.SetOutputSpacing(fixedImage.GetSpacing()) # resampler.SetOutputDirection(fixedImage.GetDirection()) # resampler.SetOutputOrigin(fixedImage.GetOrigin()) # resampler.SetDefaultPixelValue(0) # resampler.Update() # # outputImage = resampler.GetOutput() # image = itk.PyBuffer[image_type].GetArrayFromImage(outputImage) if isTime: return movingData.getData().copy(), {'Contour': new_trans_points, 'Centerline': result_center_points}, [0, 0, 0], time2 - time1 return movingData.getData().copy(), {'Contour': new_trans_points, 'Centerline': result_center_points}, [0, 0, 0]
def process(self, dataset): savepath = self.path + self.ini.file.savedir db.saveMatData(savepath + 'MR_%d_Merge_Full.mat' % self.cnt, dataset, 0) db.saveMatData(savepath + 'MR_%d_SNAP_Full.mat' % self.cnt, dataset, 1)
def register(self, fixedData, movingData, discard = False): index = self.gui.getDataIndex({'Contour': 0, 'Centerline': 1}, 'Select the object') if index is None: return None, None, None if index == 0: fixed_points = fixedData.getPointSet('Contour') moving_points = movingData.getPointSet('Contour') else: fixed_points = fixedData.getPointSet('Centerline') moving_points = movingData.getPointSet('Centerline') fixed_res = fixedData.getResolution().tolist() moving_res = movingData.getResolution().tolist() fixed_points = fixed_points.copy()[npy.where(fixed_points[:, 0] >= 0)] moving_points = moving_points.copy()[npy.where(moving_points[:, 0] >= 0)] # Use the bifurcation as the initial position fixed_bif = db.getBifurcation(fixed_points) moving_bif = db.getBifurcation(moving_points) if (fixed_bif < 0) or (moving_bif < 0): fixed_min = 0 else: temp = moving_points[:, 2:] moving_delta = moving_bif - npy.min(temp[npy.where(npy.round(temp[:, 1]) == 0), 0]) fixed_min = fixed_bif - moving_delta * moving_res[-1] / fixed_res[-1] #print moving_res #print fixed_res # Augmentation of pointset fixed = fixed_points[npy.where(fixed_points[:, 2] >= fixed_min)] moving = moving_points.copy() fixed = util.augmentPointset(fixed, int(fixed_res[-1] / moving_res[-1] + 0.5), moving.shape[0], fixed_bif) moving = util.augmentPointset(moving, int(moving_res[-1] / fixed_res[-1] + 0.5), fixed.shape[0], moving_bif) fixed = fixed[:, :3] moving = moving[:, :3] fixed[:, :3] *= fixed_res[:3] moving[:, :3] *= moving_res[:3] if (fixed_bif >= 0) and (moving_bif >= 0): fixed[:, 2] -= (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) print fixed.shape[0], moving.shape[0] #return None, None, None sourcePoints = vtk.vtkPoints() sourceVertices = vtk.vtkCellArray() for x in moving: id = sourcePoints.InsertNextPoint(x[0], x[1], x[2]) sourceVertices.InsertNextCell(1) sourceVertices.InsertCellPoint(id) source = vtk.vtkPolyData() source.SetPoints(sourcePoints) source.SetVerts(sourceVertices) targetPoints = vtk.vtkPoints() targetVertices = vtk.vtkCellArray() for x in fixed: id = targetPoints.InsertNextPoint(x[0], x[1], x[2]) targetVertices.InsertNextCell(1) targetVertices.InsertCellPoint(id) target = vtk.vtkPolyData() target.SetPoints(targetPoints) target.SetVerts(targetVertices) icp = vtk.vtkIterativeClosestPointTransform() icp.SetSource(source) icp.SetTarget(target) icp.GetLandmarkTransform().SetModeToRigidBody() icp.Modified() icp.Update() icp_filter = vtk.vtkTransformPolyDataFilter() icp_filter.SetInput(source) icp_filter.SetTransform(icp) icp_filter.Update() # Get the result transformation parameters matrix = icp.GetMatrix() T = ml.mat([matrix.GetElement(0, 3), matrix.GetElement(1, 3), matrix.GetElement(2, 3)]).T; R = ml.mat([[matrix.GetElement(0, 0), matrix.GetElement(0, 1), matrix.GetElement(0, 2)], [matrix.GetElement(1, 0), matrix.GetElement(1, 1), matrix.GetElement(1, 2)], [matrix.GetElement(2, 0), matrix.GetElement(2, 1), matrix.GetElement(2, 2)]]).I; if (fixed_bif >= 0) and (moving_bif >= 0): T[2] += (fixed_bif * fixed_res[2] - moving_bif * moving_res[2]) moving_points = movingData.getPointSet('Contour').copy() moving_center = movingData.getPointSet('Centerline').copy() new_trans_points, result_center_points = util.resliceTheResultPoints(moving_points, moving_center, 20, moving_res, fixed_res, discard, R, T) T = -T T = R * T transform = sitk.Transform(3, sitk.sitkAffine) para = R.reshape(1, -1).tolist()[0] + T.T.tolist()[0] transform.SetParameters(para) movingImage = movingData.getSimpleITKImage() fixedImage = fixedData.getSimpleITKImage() resultImage = sitk.Resample(movingImage, fixedImage, transform, sitk.sitkLinear, 0, sitk.sitkFloat32) return sitk.GetArrayFromImage(resultImage), {'Contour': trans_points, 'Centerline': result_center_points}, para + [0, 0, 0]
def process(self, dataset, i): def autoDetectContour(point, cnt, start, end, delta, res, type): self.new_points = npy.append(self.new_points, point, 0) points = point[:, :-2] d = 20 count = 0 for i in range(start + delta, end + delta, delta): center = calCentroidFromContour(points).reshape(2) image = dataset[type].getData()[i, :, :].transpose().copy() image = (image - npy.min(image)) / (npy.max(image) - npy.min(image)) * 255 down = npy.max([npy.ceil(center[0] - d / res[0]), 0]) up = npy.min([npy.floor(center[0] + d / res[0]), image.shape[0]]) left = npy.max([npy.ceil(center[1] - d / res[1]), 0]) right = npy.min([npy.floor(center[1] + d / res[1]), image.shape[1]]) crop_image = image[down : up, left : right] center -= [down, left] result = ac_segmentation(center, crop_image) a1 = ac_area(points.transpose(), image.shape) a2 = ac_area(result, crop_image.shape) rate = a2 * 1.0 / a1 if rate >= min(1.5 + count * 0.2, 2.1) or rate <= 0.7: temp_array = points.copy() if cnt != 1 and rate > 0.7: count += 1 else: temp_array = result.transpose().copy() temp_array[:, :2] += [down, left] count = 0 points = temp_array.copy() temp_array = npy.insert(temp_array, 2, [[i], [cnt]], 1) self.new_points = npy.append(self.new_points, temp_array, 0) sys.stdout.write(str(i) + ',') sys.stdout.flush() print ' ' # Segmentation of data print 'Segment Data %s...' % self.ini.file.name_result[i] tmp = dataset['fix'].pointSet.data['Contour'] tmp = tmp[tmp[:, 0] >= 0] self.new_points = npy.array([[-1, -1, -1, -1]], dtype = npy.float32) bottom = int(npy.round(npy.min(tmp[:, 2]))) bif = int(db.getBifurcation(tmp) + 0.5) up = int(npy.round(npy.max(tmp[:, 2]))) bottom += (bif - bottom) / 2 up -= (up - bif) / 2 point_vital = [0] * 3 point_vital[0] = tmp[(npy.round(tmp[:, -1]) == 0) & (npy.round(tmp[:, 2]) == bottom)].copy() point_vital[1] = tmp[(npy.round(tmp[:, -1]) == 1) & (npy.round(tmp[:, 2]) == up)].copy() point_vital[2] = tmp[(npy.round(tmp[:, -1]) == 2) & (npy.round(tmp[:, 2]) == up)].copy() autoDetectContour(point_vital[0], 0, bottom, bif, 1, dataset['fix'].getResolution().tolist(), 'fix') autoDetectContour(point_vital[1], 1, up, bif, -1, dataset['fix'].getResolution().tolist(), 'fix') autoDetectContour(point_vital[2], 2, up, bif, -1, dataset['fix'].getResolution().tolist(), 'fix') print ' ' print 'Finish segmentation for fix data. ' pointset = {'Contour': self.new_points} dataset['fix'].pointSet.data['Centerline'] = calCenterlineFromContour(pointset) self.new_points_fix = self.new_points.copy() # For mov data tmp = dataset['mov'].pointSet.data['Contour'] tmp = tmp[tmp[:, 0] >= 0] self.new_points = npy.array([[-1, -1, -1, -1]], dtype = npy.float32) bottom = int(npy.round(npy.min(tmp[:, 2]))) bif = int(db.getBifurcation(tmp) + 0.5) up = int(npy.round(npy.max(tmp[:, 2]))) bottom += (bif - bottom) / 2 up -= (up - bif) / 2 point_vital = [0] * 3 point_vital[0] = tmp[(npy.round(tmp[:, -1]) == 0) & (npy.round(tmp[:, 2]) == bottom)].copy() point_vital[1] = tmp[(npy.round(tmp[:, -1]) == 1) & (npy.round(tmp[:, 2]) == up)].copy() point_vital[2] = tmp[(npy.round(tmp[:, -1]) == 2) & (npy.round(tmp[:, 2]) == up)].copy() autoDetectContour(point_vital[0], 0, bottom, bif, 1, dataset['mov'].getResolution().tolist(), 'mov') autoDetectContour(point_vital[1], 1, up, bif, -1, dataset['mov'].getResolution().tolist(), 'mov') autoDetectContour(point_vital[2], 2, up, bif, -1, dataset['mov'].getResolution().tolist(), 'mov') print ' ' print 'Finish segmentation for mov data. ' pointset = {'Contour': self.new_points} dataset['mov'].pointSet.data['Centerline'] = calCenterlineFromContour(pointset) self.new_points_mov = self.new_points.copy() # ICP with centerline without label print 'Register Data %s with ICP(centerline) without label...' % self.ini.file.name_result[i] data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1, op = True) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis(resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole dice_index, dice_index_all = self.areaerror.analysis(resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet2.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet2.write(j + 1, i + 2, mean_dis[j]) self.sheet2.write(j + 5, i + 2, max_dis[j]) self.sheet2.write(j + 9, i + 2, dice_index[j]) self.sheet2.write(4, i + 2, mean_whole) self.sheet2.write(8, i + 2, max_whole) self.sheet2.write(12, i + 2, dice_index_all) self.book.save(self.path + self.ini.file.savedir + 'multicontrast_seg_feature.xls') del data, point, resultData # ICP with centerline with label print 'Register Data %s with ICP(centerline) with label...' % self.ini.file.name_result[i] data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 1, op = False) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis(resultData, dataset['fix'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Contour').copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole dice_index, dice_index_all = self.areaerror.analysis(resultData, dataset['fix'].getPointSet('Contour').copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet4.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet4.write(j + 1, i + 2, mean_dis[j]) self.sheet4.write(j + 5, i + 2, max_dis[j]) self.sheet4.write(j + 9, i + 2, dice_index[j]) self.sheet4.write(4, i + 2, mean_whole) self.sheet4.write(8, i + 2, max_whole) self.sheet4.write(12, i + 2, dice_index_all) self.book.save(self.path + self.ini.file.savedir + 'multicontrast_seg_feature.xls') del data, point, resultData fix_points = dataset['fix'].getPointSet('Contour').copy() dataset['fix'].pointSet.data['Contour'] = self.new_points_fix mov_points = dataset['mov'].getPointSet('Contour').copy() dataset['mov'].pointSet.data['Contour'] = self.new_points_mov print 'Saving Data %s...' % self.ini.file.name_result[i] db.saveMatData(self.path + self.ini.file.savedir + self.ini.file.name_result[i] + '_snap.mat', [dataset['fix']], 0) db.saveMatData(self.path + self.ini.file.savedir + self.ini.file.name_result[i] + '_merge.mat', [dataset['mov']], 0) print 'Done!' # ICP with contour without label print 'Register Data %s with ICP(contour) without label...' % self.ini.file.name_result[i] data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 0, op = False) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis(resultData, fix_points.copy(), mov_points.copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole para = resultData.info.getData('transform') R = ml.mat(para[:9]).reshape(3, 3) T = ml.mat(para[9:12]).T T = R.I * T T = -T tmp_con, result_center_points = util.resliceTheResultPoints(mov_points, None, 20, dataset['mov'].getResolution().tolist(), dataset['fix'].getResolution().tolist(), False, R, T) resultData.pointSet.data['Contour'] = tmp_con dice_index, dice_index_all = self.areaerror.analysis(resultData, fix_points.copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet1.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet1.write(j + 1, i + 2, mean_dis[j]) self.sheet1.write(j + 5, i + 2, max_dis[j]) self.sheet1.write(j + 9, i + 2, dice_index[j]) self.sheet1.write(4, i + 2, mean_whole) self.sheet1.write(8, i + 2, max_whole) self.sheet1.write(12, i + 2, dice_index_all) self.book.save(self.path + self.ini.file.savedir + 'multicontrast_seg_feature.xls') del data, point, resultData # ICP with contour with label print 'Register Data %s with ICP(contour) with label...' % self.ini.file.name_result[i] data, point, para = self.icp.register(dataset['fix'], dataset['mov'], 0, op = True) resultData = db.ResultData(data, db.ImageInfo(dataset['fix'].info.data), point) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', para) print 'Done!' mean_dis, mean_whole, max_dis, max_whole = self.surfaceerror.analysis(resultData, fix_points.copy(), mov_points.copy(), dataset['mov'].getPointSet('Mask').copy(), dataset['mov'].getResolution().tolist()) print 'Contour Error Done! Whole mean is %0.2fmm.' % mean_whole para = resultData.info.getData('transform') R = ml.mat(para[:9]).reshape(3, 3) T = ml.mat(para[9:12]).T T = R.I * T T = -T tmp_con, result_center_points = util.resliceTheResultPoints(mov_points, None, 20, dataset['mov'].getResolution().tolist(), dataset['fix'].getResolution().tolist(), False, R, T) resultData.pointSet.data['Contour'] = tmp_con dice_index, dice_index_all = self.areaerror.analysis(resultData, fix_points.copy()) print 'Area Error Done! Whole Dice index is %0.3f.' % dice_index_all self.sheet3.write(0, i + 2, self.ini.file.name_result[i]) for j in range(3): self.sheet3.write(j + 1, i + 2, mean_dis[j]) self.sheet3.write(j + 5, i + 2, max_dis[j]) self.sheet3.write(j + 9, i + 2, dice_index[j]) self.sheet3.write(4, i + 2, mean_whole) self.sheet3.write(8, i + 2, max_whole) self.sheet3.write(12, i + 2, dice_index_all) self.book.save(self.path + self.ini.file.savedir + 'multicontrast_seg_feature.xls') del data, point, resultData del self.new_points, fix_points, self.new_points_fix, self.new_points_mov, mov_points, tmp_con, result_center_points
def register(self, fixedData, movingData, regPara = [(40.0, 1000.0, "SSD")], w2 = 1.0, true_fixed_points = None, true_moving_points = None): # For simple test # Initial data fixed_res = fixedData.getResolution().tolist() moving_res = movingData.getResolution().tolist() fixed_points = fixedData.getPointSet('Contour') moving_points = movingData.getPointSet('Contour') fixed_points_cen = fixedData.getPointSet('Centerline') moving_points_cen = movingData.getPointSet('Centerline') fixed_points_ori = fixed_points.copy()[npy.where(fixed_points[:, 0] >= 0)] moving_points_ori = moving_points.copy()[npy.where(moving_points[:, 0] >= 0)] fixed_points_cen_ori = fixed_points_cen.copy()[npy.where(fixed_points_cen[:, 0] >= 0)] moving_points_cen_ori = moving_points_cen.copy()[npy.where(moving_points_cen[:, 0] >= 0)] if true_fixed_points is None: true_fixed_points = fixed_points_ori if true_moving_points is None: true_moving_points = moving_points_ori fixed_points = fixed_points_ori.copy() moving_points = moving_points_ori.copy() fixed_points_cen = fixed_points_cen_ori.copy() moving_points_cen = moving_points_cen_ori.copy() fix_img = fixedData.getData() mov_img = movingData.getData() init_time = 0.0 time1 = time.time() # Calculate the initial rigid transformation for 9 points T0 fix_key_point = eutil.getKeyPoints(fixed_points_cen, fixed_res) mov_key_point = eutil.getKeyPoints(moving_points_cen, moving_res) T0, mov_bif = eutil.getRigidTransform(fix_key_point, mov_key_point) # 4 * 4 Matrix moving_points = eutil.applyRigidTransformOnPoints(moving_points, moving_res, T0) moving_points_cen_result = eutil.applyRigidTransformOnPoints(moving_points_cen, moving_res, T0) crop_fixed_index, crop_moving_index = eutil.cropCenterline(fixed_points_cen, moving_points_cen_result, fixed_res, moving_res, fix_key_point[0, 2] / fixed_res[2], mov_bif[2] / moving_res[2]) # Use GMMREG for centerline-based rigid registration T1 gmm = GmmregPointsetRegistration(self.gui) new_fixedData = db.BasicData(fix_img, db.ImageInfo(fixedData.getInfo().data), {'Contour': fixed_points, 'Centerline': fixed_points_cen[crop_fixed_index]}) new_movingData = db.BasicData(mov_img, db.ImageInfo(movingData.getInfo().data), {'Contour': moving_points, 'Centerline': moving_points_cen_result[crop_moving_index]}) tmp_img, points, para = gmm.register(new_fixedData, new_movingData, 1, False, "rigid") T1 = eutil.getMatrixFromGmmPara(para) T_init = T0 * T1 moving_points = points['Contour'].copy() moving_points_cen_result = points['Centerline'].copy() del new_movingData # Use GMMREG for centerline-based TPS registration new_movingData = db.BasicData(mov_img, db.ImageInfo(fixedData.getInfo().data), {'Contour': moving_points, 'Centerline': moving_points_cen_result}) # The image has been resampled into fixed resolution tmp_img, points, para = gmm.register(new_fixedData, new_movingData, 1, False, "EM_TPS") result_points_cen = points['Centerline'].copy() result_points_cen = result_points_cen[result_points_cen[:, -1] >= 0] result_points_cen[:, :3] *= fixed_res del new_movingData del new_fixedData del moving_points_cen_result # Save the images for Elastix registration ee.writeImageFile(fixedData, "fix") ee.writeImageFile(movingData, "mov") fix_binary_mask = eutil.getBinaryImageFromSegmentation(fix_img, fixed_points_ori) fix_binary_data = db.BasicData(fix_binary_mask, db.ImageInfo(fixedData.getInfo().data)) ee.writeImageFile(fix_binary_data, "fixmm") del fix_binary_data del fix_binary_mask fix_binary_mask = eutil.getBinaryImageFromSegmentation(fix_img, true_fixed_points) fix_binary_data = db.BasicData(fix_binary_mask, db.ImageInfo(fixedData.getInfo().data)) ee.writeImageFile(fix_binary_data, "fixmmm") del fix_binary_data del fix_binary_mask mov_binary_mask = eutil.getBinaryImageFromSegmentation(mov_img, moving_points_ori) mov_binary_data = db.BasicData(mov_binary_mask, db.ImageInfo(movingData.getInfo().data)) ee.writeImageFile(mov_binary_data, "movmm") del mov_binary_data del mov_binary_mask mov_binary_mask = eutil.getBinaryImageFromSegmentation(mov_img, true_moving_points) mov_binary_data = db.BasicData(mov_binary_mask, db.ImageInfo(movingData.getInfo().data)) ee.writeImageFile(mov_binary_data, "movmmm") del mov_binary_data del mov_binary_mask fix_binary_mask = eutil.getMaskFromCenterline(fix_img, fixed_points_cen_ori, fixed_res) fix_binary_data = db.BasicData(fix_binary_mask, db.ImageInfo(fixedData.getInfo().data)) ee.writeImageFile(fix_binary_data, "fixm") del fix_binary_data del fix_binary_mask mov_binary_mask = eutil.getMaskFromCenterline(mov_img, moving_points_cen_ori, moving_res) mov_binary_data = db.BasicData(mov_binary_mask, db.ImageInfo(movingData.getInfo().data)) ee.writeImageFile(mov_binary_data, "movm") del mov_binary_data del mov_binary_mask tmp = moving_points_cen.copy() tmp[:, :3] *= moving_res ee.writePointsetFile(tmp[crop_moving_index], "movp.txt") ee.writePointsetFile(result_points_cen, "fixp.txt") init_para_inv = eutil.getElastixParaFromMatrix(T_init.I) ee.writeTransformFile(init_para_inv, fix_img.shape, fixed_res, type = "MI") # For transformation of image ee.writeTransformFile(init_para_inv, fix_img.shape, fixed_res, "transparassd.txt") # For transformation of image init_para = eutil.getElastixParaFromMatrix(T_init) ee.writeTransformFile(init_para, fix_img.shape, fixed_res, "transpara2.txt") # For transformation of points # Apply the initial transformation (It seems -t0 didn't work in Elastix) ee.run_executable(type = "transformix", mov = "movp.txt", tp = "transpara2.txt") ee.writePointsetFileFromResult("Output/outputpoints.txt", "movp0.txt") tmp = moving_points_ori.copy() tmp[:, :3] *= moving_res ee.writePointsetFile(tmp, "mov.txt") ee.run_executable(type = "transformix", mov = "mov.txt", tp = "transpara2.txt") # Transform the moving segmentation result using initial transformation ee.writePointsetFileFromResult("Output/outputpoints.txt", "mov0.txt") ee.changeOutputBSplineOrder("transpara.txt", 3) ee.run_executable(type = "transformix", mov = "mov.mhd", tp = "transpara.txt", outDir = "") ee.renameImage("result", "mov0") ee.changeOutputBSplineOrder("transpara.txt", 0) ee.run_executable(type = "transformix", mov = "movmm.mhd", tp = "transparassd.txt", outDir = "") ee.renameImage("result", "movmm0") ee.run_executable(type = "transformix", mov = "movm.mhd", tp = "transparassd.txt", outDir = "") ee.renameImage("result", "movm0") ee.run_executable(type = "transformix", mov = "movmmm.mhd", tp = "transparassd.txt", outDir = "") ee.renameImage("result", "movmmm0") sa = SurfaceErrorAnalysis(None) # Start registration of different parameters cnt = len(regPara) result = npy.zeros([cnt, 3], dtype = npy.float32) fix_img_mask = ee.readImageFile("fixmmm.mhd") time2 = time.time() init_time = time2 - time1 for i in range(0, cnt): if regPara[i][2] == "MI" and regPara[i][1] > 0: ww = regPara[i][1] / 1000 else: ww = regPara[i][1] isRigid = regPara[i][0] < 0 # Save Elastix registration configuration ee.writeParameterFile("para_rigid.txt", "rigid", regPara[i][2], regPara[i][0], ww, w2) if not isRigid: ee.writeParameterFile("para_spline.txt", "bspline", regPara[i][2], regPara[i][0], ww, w2) # Use Elastix for hybrid registration if isRigid: para_elastix = ["para_rigid.txt"] else: para_elastix = ["para_rigid.txt", "para_spline.txt"] if regPara[i][2] == "SSD": mov_name = "movmm0.mhd" fix_name = "fixmm.mhd" else: mov_name = "mov0.mhd" fix_name = "fix.mhd" time1 = time.time() code = ee.run_executable(type = "elastix", para = para_elastix, fix = fix_name, mov = mov_name, movm = "movm0.mhd", movp = "movp0.txt", mask = (regPara[i][2] != "SSD")) time2 = time.time() if code != 0: print "Elastix error!" continue # Read the output files into self data formats ee.changeOutputBSplineOrder("Output/TransformParameters.0.txt", 0) if not isRigid: ee.changeOutputBSplineOrder("Output/TransformParameters.1.txt", 0) ee.run_executable(type = "transformix", mov = "movmmm0.mhd", tp = "Output/TransformParameters.1.txt") # Non-rigid transformation ee.changeOutputInitTransform("Output/TransformParameters.1.txt") else: ee.run_executable(type = "transformix", mov = "movmmm0.mhd", tp = "Output/TransformParameters.0.txt") ee.changeOutputBSplineOrder("Output/TransformParameters.0.txt", 0) result_img_mask = ee.readImageFile("Output/result.mhd") if regPara[i][2] == "SSD": # Transform the segmentation result for evaluation ''' if isRigid: result_img_mask = ee.readImageFile("Output/result.0.mhd") else: result_img_mask = ee.readImageFile("Output/result.1.mhd") ''' if cnt == 1: #if True: ee.changeOutputBSplineOrder("Output/TransformParameters.0.txt", 3) if not isRigid: ee.changeOutputBSplineOrder("Output/TransformParameters.1.txt", 3) ee.run_executable(type = "transformix", mov = "mov0.mhd", tp = "Output/TransformParameters.1.txt") # Non-rigid transformation ee.changeOutputInitTransform("Output/TransformParameters.1.txt") else: ee.run_executable(type = "transformix", mov = "mov0.mhd", tp = "Output/TransformParameters.0.txt") result_img = ee.readImageFile("Output/result.mhd") print i, 'SSD' else: if cnt == 1: #if True: if isRigid: result_img = ee.readImageFile("Output/result.0.mhd") print i, 'Other' else: result_img = ee.readImageFile("Output/result.1.mhd") ee.generateInverseTransformFile("Output/TransformParameters.0.txt", "fix.mhd") # Delete the mask slice from the moving points tmp = true_moving_points.copy() for point in movingData.getPointSet('Mask'): tmp = npy.delete(tmp, npy.where((npy.abs(tmp[:, 2] - point[2]) < 0.0001) & (npy.round(tmp[:, -1]) == point[3])), axis = 0) tmp[:, :3] *= moving_res ee.writePointsetFile(tmp, "movm.txt") ee.run_executable(type = "transformix", mov = "movm.txt", tp = "transpara2.txt") # Transform the moving segmentation result using initial transformation ee.writePointsetFileFromResult("Output/outputpoints.txt", "mov0m.txt") ee.run_executable(type = "transformix", mov = "mov0m.txt", tp = "TransformParameters.0.txt") # Transform the moving segmentation result using rigid transformation if not isRigid: ee.generateInverseTransformFile("Output/TransformParameters.1.txt", "fix.mhd") ee.writePointsetFile(ee.readPointsetFile("Output/outputpoints.txt"), "Output/outputpoints2.txt") ee.run_executable(type = "transformix", mov = "Output/outputpoints2.txt", tp = "TransformParameters.0.txt") # Non-rigid transformation result_con = tmp.copy() result_con[:, :3] = ee.readPointsetFile("Output/outputpoints.txt") result_con[:, :3] /= fixed_res result_pointset = {'Contour': result_con} if cnt > 1: #if False: dataset = db.BasicData(npy.array([[[0]]]), fixedData.getInfo(), result_pointset) mean_dis, mean_whole, max_dis, max_whole = sa.analysis(dataset, point_data_fix = true_fixed_points, useResult = True) del dataset dice_index = eutil.calDiceIndexFromMask(fix_img_mask, result_img_mask) del result_img_mask del result_pointset del result_con result[i, :] = [mean_whole, dice_index, time2 - time1]# + init_time] print "Result of spacing %fmm, weight %f and metric %s: %fmm, %f. " % (regPara[i][0], ww, regPara[i][2], mean_whole, dice_index) ''' # Save the result resultData = db.ResultData(result_img, db.ImageInfo(fixedData.info.data), result_pointset) resultData.info.addData('fix', 1) resultData.info.addData('move', 2) resultData.info.addData('transform', [0, 0, 0]) db.saveMatData('D:/Python src/MIRVAP/Result/Result' + str(i) + '_37L.mat', [resultData, fixedData, movingData], 0) del resultData ''' del fix_img_mask if cnt > 1: result_img = None result_pointset = None else: result = [0, 0, 0] return result_img, result_pointset, result