如何使用一系列 2D 图像创建 3D 图像
How to create a 3D image with series of 2D Image
我有一系列样本的 2D tiff 图像,我想创建或复制 3D image/volume 使用这些 2D 图像进行 3D 可视化。
我发现这个 link 有类似的问题,但它讨论了使用反投影算法进行 CT 重建。但是我已经有了图像形式的样本的二维视图。
我想知道如何使用 python 或 Matlab 从那些 2D 切片(Tiff 图像)再现 3D 图像。
在对可能无关紧要的内容进行长篇解释之前,我想先确认一下这是否是您要查找的内容。
我有一系列肿瘤的二维图像。我正在从图像切片构建一个 3d shell 并从该 shell.
创建一个 .ply 文件
二维切片
3D 重建
这是您正在寻找的那种东西吗?
编辑:
我下载了数据集并通过程序运行它。
我将图像的分辨率设置为 100x100 以减少 .ply 文件中的点数。您可以根据需要增加或减少它。
创建 .ply 文件的程序
import cv2
import math
import numpy as np
import os
# creates a point cloud file (.ply) from numpy array
def createPointCloud(filename, arr):
# open file and write boilerplate header
file = open(filename, 'w');
file.write("ply\n");
file.write("format ascii 1.0\n");
# count number of vertices
num_verts = arr.shape[0];
file.write("element vertex " + str(num_verts) + "\n");
file.write("property float32 x\n");
file.write("property float32 y\n");
file.write("property float32 z\n");
file.write("end_header\n");
# write points
point_count = 0;
for point in arr:
# progress check
point_count += 1;
if point_count % 1000 == 0:
print("Point: " + str(point_count) + " of " + str(len(arr)));
# create file string
out_str = "";
for axis in point:
out_str += str(axis) + " ";
out_str = out_str[:-1]; # dump the extra space
out_str += "\n";
file.write(out_str);
file.close();
# extracts points from mask and adds to list
def addPoints(mask, points_list, depth):
mask_points = np.where(mask == 255);
for ind in range(len(mask_points[0])):
# get point
x = mask_points[1][ind];
y = mask_points[0][ind];
point = [x,y,depth];
points_list.append(point);
def main():
# tweakables
slice_thickness = .2; # distance between slices
xy_scale = 1; # rescale of xy distance
# load images
folder = "images/";
files = os.listdir(folder);
images = [];
for file in files:
if file[-4:] == ".tif":
img = cv2.imread(folder + file, cv2.IMREAD_GRAYSCALE);
img = cv2.resize(img, (100, 100)); # change here for more or less resolution
images.append(img);
# keep a blank mask
blank_mask = np.zeros_like(images[0], np.uint8);
# create masks
masks = [];
masks.append(blank_mask);
for image in images:
# mask
mask = cv2.inRange(image, 0, 100);
# show
cv2.imshow("Mask", mask);
cv2.waitKey(1);
masks.append(mask);
masks.append(blank_mask);
cv2.destroyAllWindows();
# go through and get points
depth = 0;
points = [];
for index in range(1,len(masks)-1):
# progress check
print("Index: " + str(index) + " of " + str(len(masks)));
# get three masks
prev = masks[index - 1];
curr = masks[index];
after = masks[index + 1];
# do a slice on previous
prev_mask = np.zeros_like(curr);
prev_mask[prev == 0] = curr[prev == 0];
addPoints(prev_mask, points, depth);
# # do a slice on after
next_mask = np.zeros_like(curr);
next_mask[after == 0] = curr[after == 0];
addPoints(next_mask, points, depth);
# get contour points (_, contours) in OpenCV 2.* or 4.*
_, contours, _ = cv2.findContours(curr, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE);
for con in contours:
for point in con:
p = point[0]; # contours have an extra layer of brackets
points.append([p[0], p[1], depth]);
# increment depth
depth += slice_thickness;
# rescale x,y points
for ind in range(len(points)):
# unpack
x,y,z = points[ind];
# scale
x *= xy_scale;
y *= xy_scale;
points[ind] = [x,y,z];
# convert points to numpy and dump duplicates
points = np.array(points).astype(np.float32);
points = np.unique(points.reshape(-1, points.shape[-1]), axis=0);
print(points.shape);
# save to point cloud file
createPointCloud("test.ply", points);
if __name__ == "__main__":
main();
我有一系列样本的 2D tiff 图像,我想创建或复制 3D image/volume 使用这些 2D 图像进行 3D 可视化。
我发现这个 link
我想知道如何使用 python 或 Matlab 从那些 2D 切片(Tiff 图像)再现 3D 图像。
在对可能无关紧要的内容进行长篇解释之前,我想先确认一下这是否是您要查找的内容。
我有一系列肿瘤的二维图像。我正在从图像切片构建一个 3d shell 并从该 shell.
创建一个 .ply 文件二维切片
3D 重建
这是您正在寻找的那种东西吗?
编辑:
我下载了数据集并通过程序运行它。
我将图像的分辨率设置为 100x100 以减少 .ply 文件中的点数。您可以根据需要增加或减少它。
创建 .ply 文件的程序
import cv2
import math
import numpy as np
import os
# creates a point cloud file (.ply) from numpy array
def createPointCloud(filename, arr):
# open file and write boilerplate header
file = open(filename, 'w');
file.write("ply\n");
file.write("format ascii 1.0\n");
# count number of vertices
num_verts = arr.shape[0];
file.write("element vertex " + str(num_verts) + "\n");
file.write("property float32 x\n");
file.write("property float32 y\n");
file.write("property float32 z\n");
file.write("end_header\n");
# write points
point_count = 0;
for point in arr:
# progress check
point_count += 1;
if point_count % 1000 == 0:
print("Point: " + str(point_count) + " of " + str(len(arr)));
# create file string
out_str = "";
for axis in point:
out_str += str(axis) + " ";
out_str = out_str[:-1]; # dump the extra space
out_str += "\n";
file.write(out_str);
file.close();
# extracts points from mask and adds to list
def addPoints(mask, points_list, depth):
mask_points = np.where(mask == 255);
for ind in range(len(mask_points[0])):
# get point
x = mask_points[1][ind];
y = mask_points[0][ind];
point = [x,y,depth];
points_list.append(point);
def main():
# tweakables
slice_thickness = .2; # distance between slices
xy_scale = 1; # rescale of xy distance
# load images
folder = "images/";
files = os.listdir(folder);
images = [];
for file in files:
if file[-4:] == ".tif":
img = cv2.imread(folder + file, cv2.IMREAD_GRAYSCALE);
img = cv2.resize(img, (100, 100)); # change here for more or less resolution
images.append(img);
# keep a blank mask
blank_mask = np.zeros_like(images[0], np.uint8);
# create masks
masks = [];
masks.append(blank_mask);
for image in images:
# mask
mask = cv2.inRange(image, 0, 100);
# show
cv2.imshow("Mask", mask);
cv2.waitKey(1);
masks.append(mask);
masks.append(blank_mask);
cv2.destroyAllWindows();
# go through and get points
depth = 0;
points = [];
for index in range(1,len(masks)-1):
# progress check
print("Index: " + str(index) + " of " + str(len(masks)));
# get three masks
prev = masks[index - 1];
curr = masks[index];
after = masks[index + 1];
# do a slice on previous
prev_mask = np.zeros_like(curr);
prev_mask[prev == 0] = curr[prev == 0];
addPoints(prev_mask, points, depth);
# # do a slice on after
next_mask = np.zeros_like(curr);
next_mask[after == 0] = curr[after == 0];
addPoints(next_mask, points, depth);
# get contour points (_, contours) in OpenCV 2.* or 4.*
_, contours, _ = cv2.findContours(curr, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE);
for con in contours:
for point in con:
p = point[0]; # contours have an extra layer of brackets
points.append([p[0], p[1], depth]);
# increment depth
depth += slice_thickness;
# rescale x,y points
for ind in range(len(points)):
# unpack
x,y,z = points[ind];
# scale
x *= xy_scale;
y *= xy_scale;
points[ind] = [x,y,z];
# convert points to numpy and dump duplicates
points = np.array(points).astype(np.float32);
points = np.unique(points.reshape(-1, points.shape[-1]), axis=0);
print(points.shape);
# save to point cloud file
createPointCloud("test.ply", points);
if __name__ == "__main__":
main();