使用数据转换器将 3D 体积显示为图像

Using a Data Converter to Display 3D Volume as Images

我想写一个数据转换工具。我需要分析文件中的比特流以显示 3D 体积的 2D cross-sections。

我想查看的数据集可以在这里找到:https://figshare.com/articles/SSOCT_test_dataset_for_OCTproZ/12356705

文件标题为:burned_wood_with_tape_1664x512x256_12bit.raw (832 MB)

非常感谢一些指导。如果我能得到一些软件使用数据转换将数据集显示为图像,我愿意悬赏。

由于我对这个概念完全陌生,所以我没有代码来解决这个问题。然而,这里有一些我尝试使用来自其他问题的灵感的东西:

import rawpy
import imageio

path = "Datasets/burned_wood_with_tape_1664x512x256_12bit.raw"
for item in path:
    item_path = path + item
    raw = rawpy.imread(item_path)
    rgb = raw.postprocess()
    rawpy.imshow(rgb)

我认为它根本不是有效的 RAW 文件。
如果您尝试此代码:

import rawpy
import imageio

path = 'Datasets/burned_wood_with_tape_1664x512x256_12bit.raw'
raw = rawpy.imread(path)
rgb = raw.postprocess()

您将收到以下错误:

----> 5 raw = rawpy.imread(path)
      6 rgb = raw.postprocess()

~\Anaconda3\envs\py37tf2gpu\lib\site-packages\rawpy\__init__.py in imread(pathOrFile)
     18         d.open_buffer(pathOrFile)
     19     else:
---> 20         d.open_file(pathOrFile)
     21     return d

rawpy\_rawpy.pyx in rawpy._rawpy.RawPy.open_file()

rawpy\_rawpy.pyx in rawpy._rawpy.RawPy.handle_error()

LibRawFileUnsupportedError: b'Unsupported file format or not RAW file'

下面我实现了下一个可视化。

示例 RAW 文件 burned_wood_with_tape_1664x512x256_12bit.raw 由每个 A 扫描 1664 个样本、每个 B 扫描 512 个 A 扫描、每个缓冲区 16 个 B 扫描、每个卷 16 个缓冲区以及此文件中的 2 个卷组成,每个样本都被编码为小端顺序的 2 字节无符号整数,仅使用高 12 位,低 4 位包含零。样本大约集中在 2^15 左右,准确地说数据具有这些统计信息 min 0 max 47648 mean 32757 standard deviation 454.5.

我画了1664 x 512的灰度图,一个文件中总共有16 * 16 * 2 = 512张这样的图(帧)。我使用 matplotlib 库在屏幕上绘制动画帧,还将这些动画渲染到 GIF 文件中。一个以降低质量呈现的 GIF 示例位于代码之后。

对于render/draw不同分辨率的图像,您需要使用plt.rcParams['figure.figsize']更改代码行,此图大小包含(widht_in_inches,height_in_inches),默认DPI (每英寸点数)等于 100,这意味着如果您想要生成分辨率为 720x265 的 GIF,则需要将此图形大小设置为 (7.2, 2.65)。生成的 GIF 还包含分辨率稍小的动画,因为轴和填充包含在生成的图形大小中。

我的下一个代码需要通过命令安装一次 pip 模块 python -m pip install numpy matplotlib

Try it online!

# Needs: python -m pip install numpy matplotlib
def oct_show(file, *, begin = 0, end = None):
    import os, numpy as np, matplotlib, matplotlib.pyplot as plt, matplotlib.animation
    plt.rcParams['figure.figsize'] = (7.2, 2.65) # (4.8, 1.75) (7.2, 2.65) (9.6, 3.5)
    sizeX, sizeY, cnt, bits = 1664, 512, 16 * 16 * 2, 12
    stepX, stepY = 16, 8
    fps = 5
    try:
        fsize, opened_here = None, False
        if type(file) is str:
            fsize = os.path.getsize(file)
            file, opened_here = open(file, 'rb'), True
        by = (bits + 7) // 8
        if end is None and fsize is not None:
            end = fsize // (sizeX * sizeY * by)
        imgs = []
        file.seek(begin * sizeY * sizeX * by)
        a = file.read((end - begin) * sizeY * sizeX * by)
        a = np.frombuffer(a, dtype = np.uint16)
        a = a.reshape(end - begin, sizeY, sizeX)
        amin, amax, amean, stdd = np.amin(a), np.amax(a), np.mean(a), np.std(a)
        print('min', amin, 'max', amax, 'mean', round(amean, 1), 'std_dev', round(stdd, 3))
        a = (a.astype(np.float32) - amean) / stdd
        a = np.maximum(0.1, np.minimum(a * 128 + 128.5, 255.1)).astype(np.uint8)
        a = a[:, :, :, None].repeat(3, axis = -1)
        
        fig, ax = plt.subplots()
        plt.subplots_adjust(left = 0.08, right = 0.99, bottom = 0.06, top = 0.97)
        for i in range(a.shape[0]):
            title = ax.text(
                0.5, 1.02, f'Frame {i}',
                size = plt.rcParams['axes.titlesize'],
                ha = 'center', transform = ax.transAxes,
            )
            imgs.append([ax.imshow(a[i], interpolation = 'antialiased'), title])
        ani = matplotlib.animation.ArtistAnimation(plt.gcf(), imgs, interval = 1000 // fps)
        print('Saving animated frames to GIF...', flush = True)
        ani.save(file.name + '.gif', writer = 'imagemagick', fps = fps)
        print('Showing animated frames on screen...', flush = True)
        plt.show()
    finally:
        if opened_here:
            file.close()

oct_show('burned_wood_with_tape_1664x512x256_12bit.raw')

示例输出 GIF: