def ac(
    NAME,
    priorSeg,
    followUpScan,
    followUpSegName,
    alpha=1e5,
    sigma=3,
    smoothing=3,
    threshold=0.01,
    balloon=1.0,
    iters=45,
):
    "Perform active contour on initial warped follow-up segmentation (to finalize segmentation)."
    print "Performing active contour finalization of follow-up segmentation..."
    input_fixed = followUpScan
    gray = nib.load(input_fixed)
    graydata = gray.get_data()

    # do 99% norm to 1000
    origDATA = np.array(graydata, dtype=float)
    origDATA = origDATA * 1000 / np.percentile(origDATA, 99)

    input_seg = NAME + "/" + os.path.basename(priorSeg[:-7]) + "0to1.nii.gz"
    seg = nib.load(input_seg)
    segdata = seg.get_data()

    affine = seg.get_affine()
    new_image_preAC = nib.Nifti1Image(segdata, affine)
    nib.save(new_image_preAC, followUpSegName[:-7] + "_preAC.nii.gz")

    img = segdata > 0.2

    [L, M, N] = np.shape(img)

    # Active Contour 2D
    finalseg2 = img.copy() * 0

    for n in range(0, N):
        mgac = []

        img2 = origDATA[:, :, n]
        gI = msnake.gborders(img2, alpha, sigma)

        # Morphological GAC. Initialization of the level-set.
        mgac = msnake.MorphGAC(gI, smoothing, threshold, balloon)
        mgac.levelset = img[:, :, n] > 0.2

        for ijk123 in xrange(iters):  # num iterations
            mgac.step()

        finalseg2[:, :, n] = mgac.levelset

    # Light filtering
    finalSeg = (gaussian_filter(finalseg2.copy() * 255, sigma=[3, 3, 1])) > 100
    im_data = origDATA.copy()

    # Add now narrow band sobel/watershed technique.
    for i in xrange(0, N):
        img = im_data[:, :, i]
        segslice = finalSeg[:, :, i]
        if np.max(finalSeg[:, :, i] > 0):

            erodeimg = erosion(segslice.copy(), iterations=1)
            dilateimg = dilation(segslice.copy(), iterations=1)

            seeds = img * 0
            seeds[:] = 1
            seeds[dilateimg > 0] = 0
            seeds[erodeimg > 0] = 2
            sobelFilt = sobel(np.array(img.copy(), dtype="int16"))
            mgac = watershed(sobelFilt, seeds) > 1

            finalSeg[:, :, i] = mgac > 0

            # Write the final output
    affine = seg.get_affine()
    image1 = np.uint8(finalSeg)
    new_image = nib.Nifti1Image(image1, affine)
    nib.save(new_image, followUpSegName)
Exemple #2
0
def MICOS(fileNAME):

	tic = time.clock()

	selfz =0
	selfz1 = 0
	selfz2 = 0
	selfrotD = -90
	imgObj2= nib.load(str(fileNAME))
	imgObj1 = imgObj2
	im = imgObj2
	selfaffine2 = imgObj2.get_affine()  
	selfheaderdtype = imgObj2.get_data_dtype()
	selfPSx = imgObj1.get_header()['pixdim'][1]
	selfPSy = imgObj1.get_header()['pixdim'][2]
	selfPSz = imgObj1.get_header()['pixdim'][3]
	(x,y,z) = orx.aff2axcodes(selfaffine2)
	selfOrx = x
	selfOry = y
	selfOrz = z
	ornt = orx.axcodes2ornt((x,y,z))  
	refOrnt = orx.axcodes2ornt(('R','S','A')) #was 'R', 'A', 'S'
	newOrnt = orx.ornt_transform(ornt,refOrnt)
	selfornt = ornt
	selfrefOrnt = refOrnt

	selfimg_data2 = imgObj2.get_data()       

	selfimg_data2 = orx.apply_orientation(selfimg_data2,newOrnt)

	selfimg_data2 = np.fliplr(np.rot90(selfimg_data2,1))
	im_data = selfimg_data2

	[x_si,y_si,z_si] = np.shape(im_data)

	#do 99% norm to 1000 
	im_data = np.array(im_data,dtype='float')
	im_data = im_data * 1000/np.percentile(im_data,99)
	#print np.shape(im_data)
	initialSeg = im_data.copy() * 0

	#begin user roi drawing...
	#go from middle up...
	for i in xrange(np.round(z_si/2),z_si,3):

		img = (im_data[:,:,i])

		# show the image
		if i > np.round(z_si/2):
			plt.figure(figsize=(ROI1.figwidth,ROI1.figheight))
		plt.imshow(img,cmap='gray')
		plt.colorbar()
		plt.title("outline one kidney, slice = " + str(i))

		# let user draw first ROI
		ROI1 = polydraw(roicolor='r') #let user draw first ROI

		# show the image with the first ROI
		plt.figure(figsize=(ROI1.figwidth,ROI1.figheight))
		plt.imshow(img,cmap='gray')
		plt.colorbar()
		ROI1.displayROI()
		plt.title("outline other kidney, slice = " + str(i))

		# let user draw second ROI
		ROI2 = polydraw(roicolor='b') #let user draw ROI

		initialSeg[:,:,i] = ROI1.getMask(img) + ROI2.getMask(img)


	#go from middle up...
	for i in xrange(np.round(z_si/2)-1,0,-3):

		img = (im_data[:,:,i])

		# show the image
		plt.figure(figsize=(ROI1.figwidth,ROI1.figheight))
		plt.imshow(img,cmap='gray')
		plt.colorbar()
		plt.title("outline one kidney, slice = " + str(i))

		# let user draw first ROI
		ROI1 = polydraw(roicolor='r') #let user draw first ROI

		# show the image with the first ROI
		plt.figure(figsize=(ROI1.figwidth,ROI1.figheight))
		plt.imshow(img,cmap='gray')
		plt.colorbar()
		ROI1.displayROI()
		plt.title("outline other kidney, slice = " + str(i))

		# let user draw second ROI
		ROI2 = polydraw(roicolor='b') #let user draw ROI

		initialSeg[:,:,i] = ROI1.getMask(img) + ROI2.getMask(img)

	toc = time.clock()


	#save out drawn polygon
	aff = selfaffine2
	outImage = deepcopy(initialSeg)#np.rot90(np.fliplr(self.segImg),-1)
	[x_si,y_si,z_si] = np.shape(outImage)
	#print np.shape(outImage)
	#This method works (for fastsegs)... but need more robust
	#for i in range(0,z_si):
	#    outImage[:,:,i] = np.rot90(self.segImg[:,:,z_si-1-i],-1)

	#try new method (more robust to header and affine mix-ups)
	ornt = orx.axcodes2ornt((selfOrx,selfOry,selfOrz))  
	refOrnt = orx.axcodes2ornt(('R','S','A'))
	newOrnt = orx.ornt_transform(refOrnt,ornt) #reversed these
	outImage= orx.apply_orientation(np.rot90(np.fliplr(outImage),-1),newOrnt)  
	#outImage = orx.apply_orientation(outImage,newOrnt)    
	#outImage = np.rot90(np.fliplr(outImage),-1)
	#print np.shape(outImage)
	#outImage = np.array(outImage,dtype=selfheaderdtype)
	new_image = nib.Nifti1Image(outImage,aff)

	nib.save(new_image,fileNAME[:-7]+'_polygon_MICOS.nii.gz')

	# Dilate and fill in missing slices
	initialSeg = dilation(initialSeg,iterations = 1)
	finalSeg = initialSeg.copy() * 0

	# now try convex hull method instead to better approximate missing slices (previous method is above)
	# This works but way too long. Also, would likely need to do object finding first, so compute
	# Convex hull for each kidney separately.
	while 0:
		xlist,ylist,zlist = find_3D_object_voxel_list(initialSeg)
		voxlist = np.zeros(shape=(np.shape(xlist)[0],3),dtype='int16')
		voxlist[:,0] = xlist
		voxlist[:,1] = ylist
		voxlist[:,2] = zlist
		tri = dtri(voxlist)

		# construct full voxel list
		xxlist,yylist,zzlist = find_3D_object_voxel_list((initialSeg+1)>0)

		fullvoxlist = np.zeros(shape=(np.shape(xxlist)[0],3),dtype='int16')
		fullvoxlist[:,0] = xxlist
		fullvoxlist[:,1] = yylist
		fullvoxlist[:,2] = zzlist

		finalSeg = np.array(in_hull(fullvoxlist,tri),dtype=float)
		finalSeg = np.reshape(finalSeg,(x_si,y_si,z_si))

	# Now do gaussian blur of polygon to smooth
	initialSeg = (filt.gaussian_filter(initialSeg.copy()*255,sigma=[3,3,1])) > 100

	#Begin optimized method...
	for i in xrange(0,z_si):
		img = (im_data[:,:,i])
		if np.max(initialSeg[:,:,i]>0):

			mgac = []
			gI = msnake.gborders(img,alpha=1E5,sigma=3.0) # increasing sigma allows more changes in contour
			mgac = msnake.MorphGAC(gI,smoothing=3,threshold=0.01,balloon=0.0) #was 2.5
			mgac.levelset = initialSeg[:,:,i]>0.5
			for ijk123 in xrange(100):
				mgac.step()
			finalSeg[:,:,i] = mgac.levelset
		#print i

	# Now do gaussian blur and threshold to finalize segmentation...
	finalSeg = (filt.gaussian_filter(finalSeg.copy()*255,sigma=[3,3,1])) > 100
	#using this helps with single slice errors of the active contour

	# Try adding now narrow band sobel/watershed technique.

	for i in xrange(0,z_si):
		img = (im_data[:,:,i])
		segslice = finalSeg[:,:,i]
		if np.max(finalSeg[:,:,i]>0):

			erodeimg = erosion(segslice.copy(),iterations=1)
			dilateimg = dilation(segslice.copy(),iterations=1)

			seeds = img * 0
			seeds[:] = 1
			seeds[dilateimg>0] = 0
			seeds[erodeimg>0] = 2
			sobelFilt = sobel(np.array(img.copy(),dtype='int16'))
			mgac = watershed(sobelFilt,seeds)>1

			finalSeg[:,:,i] = mgac>0

	#save out segmentation
	aff = selfaffine2
	outImage = deepcopy(finalSeg)#np.rot90(np.fliplr(self.segImg),-1)
	outImage = np.array(outImage,dtype='float')
	[x_si,y_si,z_si] = np.shape(outImage)

	#This method works (for fastsegs)... but need more robust
	#for i in range(0,z_si):
	#    outImage[:,:,i] = np.rot90(self.segImg[:,:,z_si-1-i],-1)

	#try new method (more robust to header and affine mix-ups)
	ornt = orx.axcodes2ornt((selfOrx,selfOry,selfOrz))  
	refOrnt = orx.axcodes2ornt(('R','S','A'))
	newOrnt = orx.ornt_transform(refOrnt,ornt) #reversed these
	outImage= orx.apply_orientation(np.rot90(np.fliplr(outImage),-1),newOrnt)  
	#outImage = orx.apply_orientation(outImage,newOrnt)    
	#outImage = np.rot90(np.fliplr(outImage),-1)
	new_image = nib.Nifti1Image(outImage,aff)
	nib.save(new_image,fileNAME[:-7]+'_FASTseg_MICOS.nii.gz')

	print 'time = '
	print toc - tic

	return (fileNAME[:-7]+'_FASTseg_MICOS.nii.gz')