Как указать цветовую карту при сохранении TIFF стека - PullRequest
0 голосов
/ 09 мая 2018

Я использую tifffile в python для сохранения 3-канальных стеков TIFF, которые затем я хочу прочитать в ImageJ или FIJI. Эти стеки TIFF открываются как композиты в ImageJ, причем каждому каналу назначается (предположительно по умолчанию) цветовая карта / LUT. Однако назначенные цвета - это не те цвета, которые имеют смысл для моих изображений. Моя проблема в том, что я не могу понять, как указать цветовую карту для каждого канала при сохранении изображения с помощью tifffile.

Например, я хотел бы иметь следующие назначения цветовой карты:

  • ч 0: серые
  • ч 1: зеленый
  • ч 2: красный

Вот код, который я использую для сохранения файлов:

# save hyperstack
with tifffile.TiffWriter(filename, bigtiff=False, imagej=True) as tif:
    for i in range(t_stack.shape[0]):
        tif.save(t_stack[i], metadata={'Composite mode': 'composite'})

Должны быть метаданные, сохраненные в формате tiff, который содержит информацию о цветовой карте канала, потому что я могу вручную отредактировать назначение цвета в ImageJ, а затем сохранить его, закрыть его, а затем, когда я снова открываю файл, он сохраняет мою ручную карту цветов задания. Поэтому я предполагаю, что должен быть тег метаданных (может быть, colormap?), Который можно использовать для указания цветов канала, но я не могу найти никакой информации о том, какой тег или синтаксис использовать.

Ответы [ 3 ]

0 голосов
/ 13 октября 2018

Вы можете передать ряд аргументов ключевого слова в функцию imsave tifffile. Это не очень хорошо задокументировано, так что я нашел наиболее полезным прочитать строку документации для функции save в классе TiffWriter:

https://github.com/blink1073/tifffile/blob/master/tifffile/tifffile.py#L750

Для спецификаций метаданных ImageJ TiffWriter.save затем ссылается на imagej_metadata_tags , где вы можете увидеть, какие типы данных вы можете хранить в переменной metadata_types (строка 7749):

https://github.com/blink1073/tifffile/blob/master/tifffile/tifffile.py#L7710

metadata_types = (
    ('Info', b'info', 1, _string),
    ('Labels', b'labl', None, _string),
    ('Ranges', b'rang', 1, _doubles),
    ('LUTs', b'luts', None, _ndarray),
    ('Plot', b'plot', 1, _bytes),
    ('ROI', b'roi ', 1, _bytes),
    ('Overlays', b'over', None, _bytes))

Вы можете создавать LUT для визуализации ваших данных, используя разные цветовые карты. Предположительно ваши данные - uint8, тогда LUT, которые вам понадобятся, будут иметь форму (3, 256) для 3 цветовых каналов и 256 значений интенсивности. Так что для серых, зеленых и красных LUT вам нужно что-то вроде:

import numpy as np
import tifffile

# Create a random test image
im_3frame = np.random.randint(0, 255, size=(3, 150, 250), dtype=np.uint8)
# Intensity value range
val_range = np.arange(256, dtype=np.uint8)
# Gray LUT
lut_gray = np.stack([val_range, val_range, val_range])
# Red LUT
lut_red = np.zeros((3, 256), dtype=np.uint8)
lut_red[0, :] = val_range
# Green LUT
lut_green = np.zeros((3, 256), dtype=np.uint8)
lut_green[1, :] = val_range
# Create ijmetadata kwarg
ijmeta = {'LUTs': [lut_gray, lut_red, lut_green]}
# Save image
tifffile.imsave(
    save_name,
    im_rgb,
    imagej=True,
    metadata={'mode': 'composite'},
    ijmetadata=ijmeta,
) 
0 голосов
/ 23 апреля 2019

Недавно я наткнулся на эту тему, когда искал решение для сохранения файлов TIFF с метаданными ImageJ для более чем 3 цветовых каналов в дополнение к серому каналу. Описанные выше решения были очень полезными, и я расширил пример для дополнительных каналов.

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

Чтобы добавить синий LUT, вы просто определите ndarray, как показано в примере выше для красного или зеленого LUT, но назначите значения интенсивности в диапазоне от 0 до 255 третьему массиву, в то время как два других массива (красный и зеленый) заполнены нулями.

lut_blue = np.zeros((3, 256), dtype=np.uint8)
lut_blue[2, :] = val_range

Путем «смешивания», например, основные цвета красный и зеленый теперь могут генерировать желтое LUT.

lut_yellow= np.zeros((3, 256), dtype='uint8')
lut_yellow[[0,1],:] = np.arange(256, dtype='uint8')

Пример, приведенный ниже, приведет к генерации файла TIFF с 7 каналами. Назначение цвета изображениям в стеке tiff определяется следующим образом:

ijmeta = {'LUTs': [lut_gray, lut_red, lut_green, lut_blue, lut_yellow, lut_magenta, lut_cyan]}

и может быть скорректирована по мере необходимости. Полный код, основанный на примере Дженни Фолкессон, выглядит следующим образом:

import numpy as np
from tifffile import imread, imsave

# Create a random test image
im_3frame = np.random.randint(0, 255, size=(7, 150, 250), dtype=np.uint8)
# Intensity value range
val_range = np.arange(256, dtype=np.uint8)
# Gray LUT
lut_gray = np.stack([val_range, val_range, val_range])
# Red LUT
lut_red = np.zeros((3, 256), dtype=np.uint8)
lut_red[0, :] = val_range
# Green LUT
lut_green = np.zeros((3, 256), dtype=np.uint8)
lut_green[1, :] = val_range
# Blue LUT
lut_blue = np.zeros((3, 256), dtype=np.uint8)
lut_blue[2, :] = val_range
# Yellow LUT
lut_yellow= np.zeros((3, 256), dtype='uint8')
lut_yellow[[0,1],:] = np.arange(256, dtype='uint8')
# Magenta LUT
lut_magenta= np.zeros((3, 256), dtype='uint8')
lut_magenta[[0,2],:] = np.arange(256, dtype='uint8')
# Cyan LUT
lut_cyan= np.zeros((3, 256), dtype='uint8')
lut_cyan[[1,2],:] = np.arange(256, dtype='uint8')


# Create ijmetadata kwarg
ijmeta = {'LUTs': [lut_gray, lut_red, lut_green, lut_blue, lut_yellow, lut_magenta, lut_cyan]}
# Save image
imsave(
    'test.tif',
    im_3frame,
    imagej=True,
    metadata={'mode': 'composite'},
    ijmetadata=ijmeta,
) 
0 голосов
/ 10 мая 2018

Создайте собственные теги TIFF IJMetadata (50839) и IJMetadataByteCounts (50838) самостоятельно и передайте их в tifffile.imsave в качестве дополнительных тегов. IJMetadata содержит внутренние метаданные приложения в двоичном формате. Информация о цвете находится в метаданных luts:

import struct
import numpy
import tifffile


def imagej_metadata_tags(metadata, byteorder):
    """Return IJMetadata and IJMetadataByteCounts tags from metadata dict.

    The tags can be passed to the TiffWriter.save function as extratags.

    """
    header = [{'>': b'IJIJ', '<': b'JIJI'}[byteorder]]
    bytecounts = [0]
    body = []

    def writestring(data, byteorder):
        return data.encode('utf-16' + {'>': 'be', '<': 'le'}[byteorder])

    def writedoubles(data, byteorder):
        return struct.pack(byteorder+('d' * len(data)), *data)

    def writebytes(data, byteorder):
        return data.tobytes()

    metadata_types = (
        ('Info', b'info', 1, writestring),
        ('Labels', b'labl', None, writestring),
        ('Ranges', b'rang', 1, writedoubles),
        ('LUTs', b'luts', None, writebytes),
        ('Plot', b'plot', 1, writebytes),
        ('ROI', b'roi ', 1, writebytes),
        ('Overlays', b'over', None, writebytes))

    for key, mtype, count, func in metadata_types:
        if key not in metadata:
            continue
        if byteorder == '<':
            mtype = mtype[::-1]
        values = metadata[key]
        if count is None:
            count = len(values)
        else:
            values = [values]
        header.append(mtype + struct.pack(byteorder+'I', count))
        for value in values:
            data = func(value, byteorder)
            body.append(data)
            bytecounts.append(len(data))

    body = b''.join(body)
    header = b''.join(header)
    data = header + body
    bytecounts[0] = len(header)
    bytecounts = struct.pack(byteorder+('I' * len(bytecounts)), *bytecounts)
    return ((50839, 'B', len(data), data, True),
            (50838, 'I', len(bytecounts)//4, bytecounts, True))


filename = 'FluorescentCells.tif'
image = tifffile.imread(filename)

grays = numpy.tile(numpy.arange(256, dtype='uint8'), (3, 1))
red = numpy.zeros((3, 256), dtype='uint8')
red[0] = numpy.arange(256, dtype='uint8')
green = numpy.zeros((3, 256), dtype='uint8')
green[1] = numpy.arange(256, dtype='uint8')
ijtags = imagej_metadata_tags({'LUTs': [grays, green, red]}, '>')

tifffile.imsave('test_ijmetadata.tif', image, byteorder='>', imagej=True,
                metadata={'mode': 'composite'}, extratags=ijtags)
...