我正在使用Xarray分析医学影像和区域定义的轮廓。我的xarray是像素值的3D数组,其坐标由患者坐标系(x,y,z)定义,单位为mm。
我有一系列坐标(以x,y,z表示),这些坐标定义了复杂多边形的顶点。它是一个元组列表,其中每个列表定义了z平面中的所有顶点。例如
[[(x1, y1, z1),..(xN, yN, z1)], [(x1, y1, z2),..(xM, yM, z2)], ...]
我做了一个数字,但我的医院已禁止访问我尝试过的每个图像共享网站。抱歉。
我想为这些多边形坐标定义的区域创建一个遮罩。我很难弄清楚该怎么做。指导将不胜感激!
pixel_data = np.ones((5,5,5))
x_coords = np.arange(2.4, 7.4, 1)
y_coords = np.arange(-3.6, 1.4, 1)
z_coords = np.arange(202.7, 207.7, 1)[::-1]
coords = {'x': x_coords, 'y': y_coords, 'z': z_coords}
example = xr.DataArray(pixel_data, dims=('y','x','z'), coords=coords)
数组:
<xarray.DataArray (y: 5, x: 5, z: 5)>
array([[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]],
...
Coordinates:
* x (x) float64 2.4 3.4 4.4 5.4 6.4
* y (y) float64 -3.6 -2.6 -1.6 -0.6 0.4
* z (z) float64 206.7 205.7 204.7 203.7 202.7
contours = [[(2.4, -3.6, 203.7),(3.4, 0.4, 203.7),(6.4, -1.6, 203.7)],
[(2.4, -2.6, 204.7),(4.4, 0.4, 204.7),(6.4, -3.6, 204.7)]]
每个元组中的x,y和z坐标将始终与我的数据数组中的x,y,z坐标完全匹配。
答案 0 :(得分:0)
好吧,我想我明白了。不知道这是否是最好的方法。欢迎提出建议。
需要构造一个由顶点坐标定义的多边形,必须将其转换为x,y维度中的索引坐标。构造完多边形后,分配遮罩值相对简单。见下文:
from PIL import Image, ImageDraw
import xarray as xr
import numpy as np
pixel_data = np.ones((5,5,5))
x_coords = np.arange(2.4, 7.4, 1)
y_coords = np.arange(-3.6, 1.4, 1)
z_coords = np.arange(202.7, 207.7, 1)[::-1]
coords = {'x': x_coords, 'y': y_coords, 'z': z_coords}
example = xr.DataArray(pixel_data, dims=('y','x','z'), coords=coords)
contours = [[(2.4, -3.6, 203.7),(3.4, 0.4, 203.7),(6.4, -1.6, 203.7)],
[(2.4, -2.6, 204.7),(4.4, 0.4, 204.7),(6.4, -3.6, 204.7)]]
def create_mask(array, contour_list):
'Takes in an Array we want to mask, and a contour'
'coordinate nested list.'
mask_array = xr.zeros_like(array)
slice_dict = {}
mask_dict = {}
for i, coord in enumerate(contour_list):
'Each list inside contour_list is a list of (x,y,z)'
'coordinates defining the contour on each slice. For each'
'sequence, the z coord is constant. This for-loop builds'
'a numpy array for each series of (x,y) coordinates and'
'stores them in a dict where the corresponding key is the'
'z-coordinate.'
x_start = float(example.x[0].values)
y_start = float(example.y[0].values)
spacing = float(example.x[0].values) - float(example.x[1].values)
resized = np.resize(coord, (int(np.size(coord) / 3), 3))
rtstruct_pixelArray = (resized[:,:2] - [x_start, y_start]) / spacing
rtstruct_pixelArray = np.rint(rtstruct_pixelArray)
slice_dict[coord[0][2]] = rtstruct_pixelArray
for z_slc in slice_dict.keys():
'For each z-slice, we need to draw a polygon defined by'
'the points we pulled above. We can do this with ImageDraw.'
polygon = slice_dict[z_slc].flatten().tolist()
img = Image.new('L', (example.shape[0], example.shape[1]), 0)
ImageDraw.Draw(img).polygon(polygon, outline=255, fill=255)
mask = np.array(img)
mask_dict[z_slc] = mask
for z_slc in mask_dict.keys():
'We can reassign values in mask_array with indexing.'
'We rely on sel to give us the slice we need. This works'
'because xarray does not copy the data with sel.'
mask_slice = mask_array.sel(z=z_slc, method='nearest')
mask_slice[:,:] = mask_dict[z_slc]
return mask_array
mask = create_mask(example, contours)
这是一个最低限度的示例!