Как создать 3D-изображение с помощью серии 2D-изображений

У меня есть серия 2D-изображений образца в формате tiff, я хочу создать или воспроизвести 3D-изображение/объем, используя эти 2D-изображения для 3D-визуализации.
Я нашел эту ссылку Реконструкция 3D-изображения из 2D-изображения есть аналогичный вопрос, но в нем обсуждалась реконструкция КТ с использованием алгоритма обратной проекции. Но у меня уже есть 2D-просмотр образца в виде изображения.

Я хочу знать, как я могу воспроизвести 3D-изображение из этих 2D-фрагментов (изображение Tiff) с помощью python или Matlab.


person akshahi17    schedule 18.03.2021    source источник
comment
Считать данные в контейнер, который поддерживает n-мерные данные. Объединить 2-мерные данные по третьей оси/измерению? - https://numpy.org/doc/stable/reference/routines.array-manipulation.html#joining-arrays   -  person wwii    schedule 19.03.2021
comment
Это 2D-срезы объемного сканирования (например, МРТ/КТ) или что-то еще? (если бы вы могли опубликовать пример tiff, который может помочь другим посоветовать)   -  person George Profenza    schedule 19.03.2021
comment
Используя napari, визуализировать серию изображений можно так же просто, как python -m napari *.tif, а затем переключиться в режим 3D-просмотра.   -  person cgohlke    schedule 19.03.2021
comment
Да, 2D-науки взяты из объемного сканирования Micro-CT.   -  person akshahi17    schedule 20.03.2021
comment
@wwii Это своего рода наложение изображений для формирования 3D-модели.   -  person akshahi17    schedule 20.03.2021


Ответы (1)


Я хочу убедиться, что это именно то, что вы ищете, прежде чем я буду долго объяснять то, что может быть неуместным.

У меня есть серия 2D-изображений опухоли. Я создаю трехмерную оболочку из фрагментов изображения и создаю файл .ply из этой оболочки.

2D-срезы

введите здесь описание изображения

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();
person Ian Chu    schedule 19.03.2021
comment
Да, что-то вроде того, что вы упомянули. Вот пример моего TIFF-файла [пример изображения][1] Это то, что я ищу [вывод желания][2] [1]: i.stack.imgur.com/frbQy.png [2]: i.stack.imgur.com/9abv9.png - person akshahi17; 20.03.2021
comment
Можешь кинуть ссылку на свои картинки? - person Ian Chu; 20.03.2021
comment
Кроме того, вы показываете куб как желаемый результат. Вам важно, что внутри куба, или достаточно просто увидеть текстурированные грани куба? - person Ian Chu; 20.03.2021
comment
вот ссылка на 2D-срезы, digitalrocksportal.org/projects/92/origin_data/384 - person akshahi17; 20.03.2021
comment
На самом деле каждый пиксель содержит некоторую информацию в 2D, которую я хочу видеть и в 3D. - person akshahi17; 20.03.2021
comment
Привет, @IanChu. Я запустил предоставленный вами код, однако не смог открыть сгенерированный файл .ply. Как открыть файл для просмотра? - person Nicholas TJ; 23.05.2021
comment
Я использовал Open3D (pypi.org/project/open3d) для просмотра файла. Вы можете использовать все, что может открыть файл .ply, это стандартный формат файла для 3D-материалов. - person Ian Chu; 24.05.2021