2D版的MIND

本文介绍了使用TensorFlow和PyTorch实现MIND(Modality Independent Neighbourhood Descriptor)特征的计算方法,通过图像平移、差分计算和高斯核卷积等步骤,实现了对输入图像局部变化的描述。并利用绝对误差准则比较了两幅图像的MIND特征相似性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import tensorflow as tf
import numpy as np
import tensorflow_addons as tfa
import SimpleITK as sitk
print(tf.__version__)
import tensorflow as tf
import matplotlib.pyplot as plt

gpus = tf.config.experimental.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(gpus[0], True)
def gaussian_kernel(sigma, sz):
    xpos_vec = np.arange(sz)
    ypos_vec = np.arange(sz)
    output = np.ones([sz, sz, 1, 1], dtype=np.single)
    midpos = sz // 2
    for xpos in xpos_vec:
        for ypos in ypos_vec:
            output[xpos,ypos,:,:] = np.exp(-((xpos-midpos)**2 + (ypos-midpos)**2) / (2 * sigma**2)) / (2 * np.pi * sigma**2)
    return output
def tf_image_translate(input_, tx, ty, interpolation='NEAREST'):
    # got these parameters from solving the equations for pixel translations
    # on https://www.tensorflow.org/api_docs/python/tf/contrib/image/transform
    transforms = [1, 0, -tx, 0, 1, -ty, 0, 0]
    return tfa.image.transform(input_, transforms, interpolation)
def Dp(image, xshift, yshift, sigma, patch_size):
    shift_image = tf_image_translate(image, xshift, yshift, interpolation='NEAREST')#将image在x、y方向移动I`(a)
    diff = tf.subtract(image, shift_image)#计算差分图I-I`(a)
    diff_square = tf.multiply(diff, diff)#(I-I`(a))^2
    res = tf.nn.conv2d(diff_square, filters=gaussian_kernel(sigma, patch_size), strides=[1,1,1,1], padding="SAME", name="patch_distance")#C*(I-I`(a))^2
    return res
def MIND(image, patch_size, neigh_size, sigma, eps,image_size0,image_size1,  name='MIND'):
    # compute the Modality independent neighbourhood descriptor (MIND) of input image.
    # suppose the neighbor size is R, patch size is P.
    # input image is 384 x 256 x input_c_dim
    # output MIND is (384-P-R+2) x (256-P-R+2) x R*R
    reduce_size = int((patch_size + neigh_size - 2) / 2)#卷积后减少的size

    # estimate the local variance of each pixel within the input image.
    Vimg = tf.add(Dp(image, -1, 0, sigma, patch_size), Dp(image, 1, 0, sigma, patch_size))
    Vimg = tf.add(Vimg, Dp(image, 0, -1, sigma, patch_size))
    Vimg = tf.add(Vimg, Dp(image, 0, 1, sigma, patch_size))#sum(Dp)
    Vimg = tf.divide(Vimg,4) + tf.multiply(tf.ones_like(Vimg), eps)#防除零

    # estimate the (R*R)-length MIND feature by shifting the input image by R*R times.
    xshift_vec = np.arange( -(neigh_size//2), neigh_size - (neigh_size//2))#邻域计算
    yshift_vec = np.arange(-(neigh_size // 2), neigh_size - (neigh_size // 2))#邻域计算
    iter_pos = 0
    for xshift in xshift_vec:
        for yshift in yshift_vec:
            if (xshift,yshift) == (0,0):
                continue
            MIND_tmp = tf.exp(tf.multiply(tf.divide(Dp(image, xshift, yshift,  sigma, patch_size), Vimg), -1))#exp(-D(I)/V(I))
            tmp = tf.image.crop_to_bounding_box(MIND_tmp, reduce_size, reduce_size, image_size0 - 2 * reduce_size, image_size1 - 2 * reduce_size)#crop
            if iter_pos == 0:
                output = tmp
            else:
                output = tf.concat([output,tmp], 3)
            iter_pos = iter_pos + 1
    # normalization.
    output = tf.divide(output, tf.expand_dims(tf.reduce_max(output, axis=3),axis=-1))

    return output
def abs_criterion(in_, target):
    return tf.reduce_mean(tf.abs(in_ - target))
if __name__ == '__main__':
    patch_size=7
    neigh_size=9
    sigma=2.0
    eps=1e-5
    image_size0=512
    image_size1=512
    ct_path = r'F:\dataset\coarseReg\00001_SRO1_ct_axial_drr.nii.gz'
    mr_path = r'F:\dataset\coarseReg\00001_SRO1_mr_axial_drr.nii.gz'
    ct_sitk = sitk.ReadImage(ct_path,sitk.sitkFloat32)
    mr_sitk = sitk.ReadImage(mr_path,sitk.sitkFloat32)

    ct_axial_drr = sitk.GetArrayFromImage(ct_sitk)[np.newaxis,:,: ,np.newaxis]
    mr_axial_drr = sitk.GetArrayFromImage(mr_sitk)[np.newaxis,:,: ,np.newaxis]

    ct_axial_drr = tf.Variable(ct_axial_drr)
    mr_axial_drr = tf.Variable(mr_axial_drr)

    A_MIND = MIND(ct_axial_drr,  patch_size, neigh_size, sigma, eps,image_size0,image_size1,  name='realA_MIND')
    B_MIND = MIND(mr_axial_drr,  patch_size, neigh_size, sigma, eps,image_size0,image_size1,  name='realA_MIND')

    g_loss_MIND = abs_criterion(A_MIND, B_MIND)
    print('g_loss_MIND', g_loss_MIND)

 

 

import torch
import numpy as np
import torchvision
import SimpleITK as sitk
import torch.nn.functional as F
import matplotlib.pyplot as plt
def gaussian_kernel(sigma, sz):
    xpos_vec = np.arange(sz)
    ypos_vec = np.arange(sz)
    output = np.ones([1, 1,sz, sz], dtype=np.single)
    midpos = sz // 2
    for xpos in xpos_vec:
        for ypos in ypos_vec:
            output[:,:,xpos,ypos] = np.exp(-((xpos-midpos)**2 + (ypos-midpos)**2) / (2 * sigma**2)) / (2 * np.pi * sigma**2)
    return output
def torch_image_translate(input_, tx, ty, interpolation='nearest'):
    # got these parameters from solving the equations for pixel translations
    # on https://www.tensorflow.org/api_docs/python/tf/contrib/image/transform
    translation_matrix = torch.zeros([1, 3, 3], dtype=torch.float)
    translation_matrix[:, 0, 0] = 1.0
    translation_matrix[:, 1, 1] = 1.0
    translation_matrix[:, 0, 2] = -2*tx/(input_.size()[2]-1)
    translation_matrix[:, 1, 2] = -2*ty/(input_.size()[3]-1)
    translation_matrix[:, 2, 2] = 1.0
    grid = F.affine_grid(translation_matrix[:, 0:2, :], input_.size()).to(input_.device)
    wrp = F.grid_sample(input_, grid, mode=interpolation)
    return wrp
def Dp(image, xshift, yshift, sigma, patch_size):
    shift_image = torch_image_translate(image, xshift, yshift, interpolation='nearest')#将image在x、y方向移动I`(a)
    diff = torch.sub(image, shift_image)#计算差分图I-I`(a)
    diff_square = torch.mul(diff, diff)#(I-I`(a))^2
    res = torch.conv2d(diff_square, weight =torch.from_numpy(gaussian_kernel(sigma, patch_size)), stride=1, padding=3)#C*(I-I`(a))^2
    return res

def MIND(image, patch_size, neigh_size, sigma, eps,image_size0,image_size1,  name='MIND'):
    # compute the Modality independent neighbourhood descriptor (MIND) of input image.
    # suppose the neighbor size is R, patch size is P.
    # input image is 384 x 256 x input_c_dim
    # output MIND is (384-P-R+2) x (256-P-R+2) x R*R
    reduce_size = int((patch_size + neigh_size - 2) / 2)#卷积后减少的size

    # estimate the local variance of each pixel within the input image.
    Vimg = torch.add(Dp(image, -1, 0, sigma, patch_size), Dp(image, 1, 0, sigma, patch_size))
    Vimg = torch.add(Vimg, Dp(image, 0, -1, sigma, patch_size))
    Vimg = torch.add(Vimg, Dp(image, 0, 1, sigma, patch_size))#sum(Dp)
    Vimg = torch.div(Vimg,4) + torch.mul(torch.ones_like(Vimg), eps)#防除零
    # estimate the (R*R)-length MIND feature by shifting the input image by R*R times.
    xshift_vec = np.arange( -(neigh_size//2), neigh_size - (neigh_size//2))#邻域计算
    yshift_vec = np.arange(-(neigh_size // 2), neigh_size - (neigh_size // 2))#邻域计算
    iter_pos = 0
    for xshift in xshift_vec:
        for yshift in yshift_vec:
            if (xshift,yshift) == (0,0):
                continue
            MIND_tmp = torch.exp(torch.mul(torch.div(Dp(image, xshift, yshift,  sigma, patch_size), Vimg), -1))#exp(-D(I)/V(I))
            tmp = MIND_tmp[:, :, reduce_size:(image_size0 - reduce_size), reduce_size:(image_size1 - reduce_size)]
            if iter_pos == 0:
                output = tmp
            else:
                output = torch.cat([output,tmp], 1)
            iter_pos = iter_pos + 1

    # normalization.
    input_max, input_indexes = torch.max(output, dim=1)
    output = torch.div(output,input_max)

    return output
def abs_criterion(in_, target):
    return torch.mean(torch.abs(in_ - target))
if __name__ == '__main__':
    patch_size=7
    neigh_size=9
    sigma=2.0
    eps=1e-5
    image_size0=512
    image_size1=512
    ct_path = r'F:\dataset\coarseReg\00001_SRO1_ct_axial_drr.nii.gz'
    mr_path = r'F:\dataset\coarseReg\00001_SRO1_mr_axial_drr.nii.gz'
    ct_sitk = sitk.ReadImage(ct_path,sitk.sitkFloat32)
    mr_sitk = sitk.ReadImage(mr_path,sitk.sitkFloat32)

    ct_axial_drr = sitk.GetArrayFromImage(ct_sitk)[np.newaxis ,np.newaxis,:,:]
    mr_axial_drr = sitk.GetArrayFromImage(mr_sitk)[np.newaxis ,np.newaxis,:,: ]

    plt.imshow(ct_axial_drr.squeeze())
    plt.show()

    ct_axial_drr = torch.from_numpy(ct_axial_drr)
    mr_axial_drr = torch.from_numpy(mr_axial_drr)

    A_MIND = MIND(ct_axial_drr,  patch_size, neigh_size, sigma, eps,image_size0,image_size1,  name='realA_MIND')
    B_MIND = MIND(mr_axial_drr,  patch_size, neigh_size, sigma, eps,image_size0,image_size1,  name='realA_MIND')
    g_loss_MIND = abs_criterion(A_MIND, B_MIND)
    print('g_loss_MIND', g_loss_MIND)

    # tf =  np.load( r"C:\Users\shcho\Desktop\validation\tf.npy" )
    # tc =  np.load( r"C:\Users\shcho\Desktop\validation\tc.npy" )

    # plt.imshow(tf)
    # plt.show()
    # plt.imshow(tc)
    # plt.show()
    # print(tf.shape, tc.shape)
    #
    # # print(tf.transpose((2,0,1)).shape, tc.shape)
    # t = tf.transpose((2,0,1)) -tc
    #
    # # t = tf -tc
    #
    # print(np.max(t))

参考:https://github.com/Grape-A/sc-cyclegan

https://arxiv.org/pdf/1809.04536.pdf

感觉效果一般没有直接改用MIND3D 到 2D的好用

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值