numpy转vtk并切片

使用的是
python3.8.10
vtk9.2.6

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2

from vtkmodules.vtkRenderingCore import (
    vtkImageActor,
    vtkRenderer,
    vtkRenderWindow,
    vtkRenderWindowInteractor
)
from vtkmodules.vtkIOImage import (
    vtkImageImport
)
from vtkmodules.vtkCommonMath import (
    vtkMatrix4x4
)
from vtkmodules.vtkCommonCore import (
    vtkLookupTable
)
from vtkmodules.vtkImagingCore import (
    vtkImageReslice,
    vtkImageMapToColors
)
from vtkmodules.vtkInteractionStyle import (
    vtkInteractorStyleImage
)
import SimpleITK as sitk
import numpy as np


def numpy2vtkImageImport(source_numpy, spacing=None, origin=None, direction=None, as_uint8=False):
    """
    numpy转成vtkImageImport

    :param source_numpy: numpy格式的图片(z,y,x)(A,C,S)
    :param spacing: 像素的间隔
    :param origin: 图片的原点
    :param direction: 方向
    :param as_uint8: 转成uint8
    :return: vtkImageImport
    """
    importer = vtkImageImport()
    origin_type = source_numpy.dtype
    if as_uint8:
        origin_type = np.uint8
        source_numpy = source_numpy.astype('uint8')
    # else:
    #     source_numpy = source_numpy.astype('int32')
    img_string = source_numpy.tobytes()
    dim = source_numpy.shape  # (z,y,x),(A,C,S)

    importer.CopyImportVoidPointer(img_string, len(img_string))
    if as_uint8:
        importer.SetDataScalarTypeToUnsignedChar()
    elif np.int16 == origin_type:
        importer.SetDataScalarTypeToShort()
    elif np.float32 == origin_type:
        importer.SetDataScalarTypeToDouble()
    else:
        importer.SetDataScalarTypeToInt()
    importer.SetNumberOfScalarComponents(1)

    extent = importer.GetDataExtent()  # 0,0,0,0,0,0
    # 图像的维度=(extent[1]-extent[0]+1) * (extent[3]-extent[2]+1) * (extent[5]-DataExtent[4]+1)=(x,y,z)=(S,C,A)
    # importer.SetDataExtent(extent[0], extent[0] + dim[2] - 1,
    #                        extent[2], extent[2] + dim[1] - 1,
    #                        extent[4], extent[4] + dim[0] - 1)
    importer.SetWholeExtent(extent[0], extent[0] + dim[2] - 1,
                            extent[2], extent[2] + dim[1] - 1,
                            extent[4], extent[4] + dim[0] - 1)
    importer.SetDataExtentToWholeExtent()
    if spacing is not None:
        importer.SetDataSpacing(*spacing)
    if origin is not None:
        importer.SetDataOrigin(*origin)
    if direction is not None:
        importer.SetDataDirection(direction)
    importer.Update()
    return importer


def resliceByOrient(vtk_data, center, ori):
    """
    重采样

    :param vtk_data: vtk的数据
    :param center: 采样中心(S,C,A)(x,y,z)
    :param ori: 1:S(x),2:C(y),0:A(z)
    :return: 重采样的数据
    """
    if 1 == ori:
        # 矢状面(sagittal plane)S(x)
        elements = [
            0, 0, -1, 0,
            1, 0, 0, 0,
            0, -1, 0, 0,
            0, 0, 0, 1
        ]
    elif 2 == ori:
        # 冠状面(coronal plane)C(y)
        elements = [
            1, 0, 0, 0,
            0, 0, 1, 0,
            0, -1, 0, 0,
            0, 0, 0, 1
        ]
    elif 0 == ori:
        # 横断面(transverse plane)A(z)
        elements = [
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1
        ]
    else:
        # 斜切切片
        elements = [
            1, 0, 0, 0,
            0, 0, 8.66025, -0.5, 0,
            0, 0.5, 0.866025, 0,
            0, 0, 0, 1
        ]
    resliceAxes = vtkMatrix4x4()
    resliceAxes.DeepCopy(elements)
    for i in range(3):
        resliceAxes.SetElement(i, 3, center[i])
        # resliceAxes.SetElement(i, 3, int(center[i]))
    reslice = vtkImageReslice()
    reslice.SetInputConnection(vtk_data.GetOutputPort())
    reslice.SetOutputDimensionality(2)
    reslice.SetResliceAxes(resliceAxes)
    reslice.SetInterpolationModeToLinear()
    reslice.Update()
    return reslice


def get_color_table(is_image, minimum=None, maximum=None, window=None, level=None):
    """
    获取颜色映射表

    :param is_image: 是否为图像
    :param minimum: 最小值
    :param maximum: 最大值
    :param window: 窗宽
    :param level: 窗位
    :return: 颜色映射表
    """
    colorTable = vtkLookupTable()
    if is_image:
        if minimum is None and maximum is None and window is not None and level is not None:
            minimum = (2 * level - window) / 2.0 + 0.5
            maximum = (2 * level + window) / 2.0 + 0.5
        elif minimum is None or maximum is None:
            raise Exception("can't get right min max")

        # 像素最小值到最大值,(可以根据窗宽窗位计算出像素范围)
        colorTable.SetRange(minimum, maximum)
        colorTable.SetValueRange(0.0, 1.0)
        colorTable.SetSaturationRange(0.0, 0.0)
        colorTable.SetRampToLinear()
    else:
        # TODO 改成正常的颜色
        colorTable.SetNumberOfTableValues(5)
        colorTable.SetRange(0.0, 4.0)
        colorTable.SetTableValue(0, 0, 0.0, 0.0, 0.0)
        colorTable.SetTableValue(1, 0.0, 1.0, 0.0, 0.4)
        colorTable.SetTableValue(2, 1.0, 0.0, 0.0, 0.4)
        colorTable.SetTableValue(3, 0.0, 0.0, 1.0, 0.4)
        colorTable.SetTableValue(4, 0.0, 0.0, 1.0, 0.4)
    colorTable.Build()
    return colorTable


if __name__ == '__main__':
    src = sitk.ReadImage('RibFrac101-image.nii.gz')
    spacing = src.GetSpacing()
    origin = src.GetOrigin()
    direction = src.GetDirection()
    source_numpy = sitk.GetArrayFromImage(src)
    vtk_data = numpy2vtkImageImport(source_numpy, spacing, origin, direction)
    print(vtk_data.GetDataExtent())
    print(vtk_data.GetDataOrigin())
    print(vtk_data.GetDataSpacing())
    print(vtk_data.GetDataDirection())
    # 257,414,177表示对应面的切片
    center = [
        origin[0] + spacing[0] * 257,  # 矢状面(sagittal plane)S
        origin[1] + spacing[1] * 414,  # 冠状面(coronal plane)C
        origin[2] + spacing[2] * 177,  # 横断面(transverse plane)A
    ]
    print(center)
    reslice = resliceByOrient(vtk_data, center, 1)
    colorTable = get_color_table(True, *(vtk_data.GetOutput().GetScalarRange()))

    colorMap = vtkImageMapToColors()
    colorMap.SetLookupTable(colorTable)
    colorMap.SetInputConnection(reslice.GetOutputPort())
    colorMap.Update()

    imgActor = vtkImageActor()
    imgActor.SetInputData(colorMap.GetOutput())

    renderer = vtkRenderer()
    renderer.AddActor(imgActor)
    renderer.SetBackground(0.0, 0.0, 0.0)

    renderWindow = vtkRenderWindow()
    renderWindow.AddRenderer(renderer)
    renderWindow.SetSize(640, 400)

    rwi = vtkRenderWindowInteractor()
    imageStyle = vtkInteractorStyleImage()
    rwi.SetInteractorStyle(imageStyle)
    rwi.SetRenderWindow(renderWindow)
    rwi.Initialize()
    renderWindow.Render()
    rwi.Start()



参考

《VTK图形图像开发进阶》P97 三维图像切面提取

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nightmare004

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值