Анализ изображений Python: чтение многомерного файла TIFF из конфокальной микроскопии

У меня есть файл изображения TIFF из конфокального микроскопа, который я могу открыть в ImageJ, но который я хотел бы получить в Python.

Формат TIFF выглядит следующим образом: в измерении Z имеется 30 стеков. Каждый слой Z имеет три канала от разных флуоресцентных маркеров. Каждый канал имеет глубину 8 бит. Размеры изображения 1024х1024.

В принципе, я могу прочитать файл с помощью Skimage (который я планирую использовать для дальнейшего анализа данных) с помощью плагина tifffile. Однако то, что я получаю, не совсем то, что я ожидаю.

merged = io.imread("merge.tif", plugin="tifffile")
merged.shape
# (30, 3, 3, 1024, 1024)
# (zslice, RGB?, channel?, height, width)
merged.dtype
# dtype('uint16')

Поначалу меня смутило то, что я получил две оси длины 3. Я думаю, что это потому, что tifffile обрабатывает каждый канал как отдельные изображения RGB, но я могу обойти это путем поднабора или использования skimage.color.rgb2grey на отдельных каналах. Больше всего меня беспокоит то, что файл импортируется как 16-битное изображение. Я могу преобразовать его обратно, используя skimage.img_as_ubyte, но после этого гистограмма больше не соответствует той, которую я вижу в ImageJ.

Я не зациклен на использовании Skimage для импорта файла, но я хотел бы в конечном итоге получить изображение в массиве, чтобы использовать в нем функции Skimage.

2 ответа

Я столкнулся с той же проблемой при работе с файлами.tif. Рекомендую использовать биоформаты пакета python.

    import javabridge
    import bioformats

    javabridge.start_vm(class_path=bioformats.JARS)

    path_to_data = '/path/to/data/file_name.tif'

    # get XML metadata of complete file
    xml_string = bioformats.get_omexml_metadata(path_to_data)
    ome = bioformats.OMEXML(xml_string) # be sure everything is ascii
    print ome.image_count

в зависимости от данных один файл может содержать несколько изображений. Каждое изображение может быть доступно следующим образом:

    # read some metadata
    iome = ome.image(0) # e.g. first image
    print iome.get_Name()
    print iome.get_ID()

    # get pixel meta data
    print iome.Pixels.get_DimensionOrder()
    print iome.Pixels.get_PixelType()
    print iome.Pixels.get_SizeX()
    print iome.Pixels.get_SizeY()
    print iome.Pixels.get_SizeZ()
    print iome.Pixels.get_SizeT()
    print iome.Pixels.get_SizeC()
    print iome.Pixels.DimensionOrder

загрузка необработанных данных изображения 0 в массив numpy выполняется следующим образом:

    reader = bioformats.ImageReader(path_to_data)
    raw_data = []
    for z in range(iome.Pixels.get_SizeZ()):
        # returns 512 x 512 x SizeC array (SizeC = number of channels)
        raw_image = reader.read(z=z, series=0, rescale=False) 
        raw_data.append(raw_image)
    raw_data = np.array(raw_data) # 512 x 512 x SizeC x SizeZ array

Надеюсь, что это помогает обрабатывать файлы.tif, ура!

Я не уверен, что 'hyperstack to stack' Функция это то, что вы хотите. Гиперстеки - это просто многомерные изображения, которые могут быть 4D или 5D (ширина, высота, срезы, каналы (например, 3 для RGB) и временные рамки). В ImageJ у вас есть ползунок для каждого измерения в гиперстеке.

Стеки - это просто двухмерные изображения, которые как-то связаны, и у вас есть только один ползунок, в простейшем случае он представляет z-срезы в наборе трехмерных данных.

'hyperstack to stack' функция суммирует все измерения в вашем гиперштеке. Таким образом, если у вас есть гиперстек с 3 каналами, 4 срезами и 5 таймфреймами (3 слайдера), вы получите стек 3x4x5 = 60 изображения (один слайдер). В основном то же самое, что вы упомянули выше со скольжением через фокальные плоскости для каждого канала. Вы можете пойти другим путем, используя 'stack to hyperstack' и сделайте гиперстек, определив, какие срезы из вашего стека представляют какое измерение. В упомянутом выше примере файла выберите порядок xyzct, 3 канала и 7 временных точек.

Так что, если ваш TIFF-файл имеет 2 ползунка, кажется, что это 4-мерный гиперстек с высотой, шириной, 30 срезами и 3 каналами. 'hyperstack to stack' сложит все размеры друг на друга, так что вы получите 3x30=90 slices,

Однако, по словам читателя tiff скимаджа, кажется, что ваш tiff-файл - это своего рода 5-мерный гиперстек. Ширина, высота (1024x1024), 30 z-слайсов, 3 канала (RGB) и другое измерение с 3 записями (например, временные рамки).

Чтобы выяснить, что не так, я бы посоветовал сравнить размеры с 3 записями массива, которые вы получаете из лыжного мага. Узнайте, какой из них представляет каналы RGB, а какой - другой. Вы можете, например, использовать функцию изображения pyqtgraph:

import pyqtgraph as pg
merged = io.imread("merge.tif", plugin="tifffile")

#pg.image takes the dimensions in the following order: z-slider,x,y,RGB channel
#if merged.shape = (30, 3, 3, 1024, 1024), you have to compare the 1st and 2nd dimension

pg.image(merged[:,0,:,:,:].transpose(0, 2, 3, 1))
pg.image(merged[:,1,:,:,:].transpose(0, 2, 3, 1))
pg.image(merged[:,2,:,:,:].transpose(0, 2, 3, 1))

pg.image(merged[:,:,0,:,:].transpose(0, 2, 3, 1))
pg.image(merged[:,:,1,:,:].transpose(0, 2, 3, 1))
pg.image(merged[:,:,2,:,:].transpose(0, 2, 3, 1))
Другие вопросы по тегам