vtk:如何从世界点获取图像像素索引

vtk: how to obtain the image pixel index from a world point

如果我从图像中选取世界点,如何将世界坐标转换为图像索引?

import vtk
import numpy as np
from vtk.util.numpy_support import numpy_to_vtk
def numpyToVTK(data, multi_component=False, type='float'):
    if type == 'float':
        data_type = vtk.VTK_FLOAT
    elif type == 'char':
        data_type = vtk.VTK_UNSIGNED_CHAR
    else:
        raise RuntimeError('unknown type')
    if multi_component == False:
        if len(data.shape) == 2:
            data = data[:, :, np.newaxis]
        flat_data_array = data.transpose(2,1,0).flatten()
        vtk_data = numpy_to_vtk(num_array=flat_data_array, deep=True, array_type=data_type)
        shape = data.shape
    else:
        assert len(data.shape) == 3, 'only test for 2D RGB'
        flat_data_array = data.transpose(1, 0, 2)
        flat_data_array = np.reshape(flat_data_array, newshape=[-1, data.shape[2]])
        vtk_data = numpy_to_vtk(num_array=flat_data_array, deep=True, array_type=data_type)
        shape = [data.shape[0], data.shape[1], 1]
    img = vtk.vtkImageData()
    img.GetPointData().SetScalars(vtk_data)
    img.SetDimensions(shape[0], shape[1], shape[2])
    return img
global sphereActor, textActor
sphereActor = None
textActor = None
def mouseMoveEvent(iren, event):
    x, y = iren.GetEventPosition()

    picker = vtk.vtkWorldPointPicker()
    picker.Pick(x, y, 0, render)
    worldPoint = picker.GetPickPosition()
    
    ##############################################
    ## convert world point to image index
    ##############################################

    sphere = vtk.vtkSphereSource()
    sphere.SetCenter(worldPoint[0], worldPoint[1], worldPoint[2])
    sphere.SetRadius(2)
    sphere.Update()
    sphereMapper = vtk.vtkPolyDataMapper()
    sphereMapper.SetInputData(sphere.GetOutput())
    global sphereActor, textActor
    if sphereActor != None:
        render.RemoveActor(sphereActor)
    sphereActor = vtk.vtkActor()
    sphereActor.SetMapper(sphereMapper)
    sphereActor.GetProperty().SetColor(255, 0, 0)
    render.AddActor(sphereActor)
    render.Render()

    if textActor != None:
        render.RemoveActor(textActor)
    textActor = vtk.vtkTextActor()
    textActor.SetInput('world coordinate: (%.2f, %.2f, %.2f)'%(worldPoint[0], worldPoint[1], worldPoint[2]))
    textActor.GetTextProperty().SetColor(1, 0, 0)
    textActor.GetTextProperty().SetFontSize(15)
    render.AddActor(textActor)


img = np.zeros(shape=[128, 128])
for i in range(128):
    for j in range(128):
        img[i, j] = i+j

vtkImg = numpyToVTK(img)
imgActor = vtk.vtkImageActor()
imgActor.SetInputData(vtkImg)

render = vtk.vtkRenderer()
render.AddActor(imgActor)
# render.Render()

renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(render)
renWin.Render()
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
iren.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
iren.Initialize()
iren.AddObserver('MouseMoveEvent', mouseMoveEvent)
iren.Start()

在上面的代码中,如果我不旋转图像,世界点是(x, y, 0):

这与我所知道的一致。对于世界点(x,y,z)和图像索引(i,j,k),转换应该是:

worldPoint (x,y,z) = i*spacingX*directionX + j*spacingY*directionY + k*spacingZ*directionZ + originPoint

上述代码中,图片是从numpy转过来的,因此:


directionX = [1, 0, 0]
directionY = [0, 1, 0]
directionZ = [0, 0, 1]
originPoint=[0, 0, 0]
spacingX=1
spacingY=1
spacingZ=1

这样,x=i, y=j, z=k。由于此图像是二维图像,因此 k 应为 0,'z' 也应为 0。

然后,我旋转图像,z不是0。如下图。

我不知道为什么z是-0.24。

说明下面的转换是错误的。以及如何通过世界点获取图像索引?

worldPoint (x,y,z) = i*spacingX*directionX + j*spacingY*directionY + k*spacingZ*directionZ + originPoint

如有任何建议,我们将不胜感激!

vtkImageData 有方法 TransformPhysicalPointToContinuousIndex 用于从世界 space 到图像 space 和 TransformIndexToPhysicalPoint 去另一条路。

我认为你所做的计算不正确,因为方向是 3x3 旋转矩阵。