Анализ текстуры GLCM: исправление инвертированных результатов однородности
Узнайте, почему значения однородности GLCM инвертируются при анализе ядер клеток, и узнайте улучшенные методы количественной оценки различий текстуры в изображениях флуоресцентной микроскопии.
Как правильно количественно оценить различия текстуры в ядрах клеток с использованием GLCM в MATLAB? Я анализирую изображения флуоресцентной микроскопии ядер клеток, где некоторые имеют зернистую/агрегированную текстуру, а другие более однородную. Несмотря на использование Матрицы совместного встречаемости уровней серого (GLCM) с различными параметрами расстояния, я получаю неожиданные результаты, при которых зернистое ядро показывает большую однородность, чем однородное. Вот мой подход в MATLAB:
% Рассчитать количество ядер в изображении
nnuclei = max(In(:));
% Инициализировать векторы для хранения извлеченных данных
intensities = zeros(1, nnuclei);
contrasts = zeros(1, nnuclei);
homogeneities = zeros(1, nnuclei);
% Для каждого ядра в изображении
for n = 1:nnuclei
% Создать маску для текущего ядра
nuclei_n = (In == n);
% Извлечь значения флуоресцентной интенсивности
nuclei_n_intensities = Idapi(nuclei_n);
intensities(n) = mean(nuclei_n_intensities);
% Анализ текстуры с использованием GLCM
L = 32; % Квантование до 32 уровней
% Обрезать до области ядра
[min_row,max_row] = deal(find(any(nuclei_n, 2),1,'first'), find(any(nuclei_n, 2),1,'last'));
[min_col,max_col] = deal(find(any(nuclei_n, 1),1,'first'), find(any(nuclei_n, 1),1,'last'));
In_crop = Idapi(min_row:max_row, min_col:max_col);
nuclei_n_crop = nuclei_n(min_row:max_row, min_col:max_col);
% Квантование пикселей ядра
In_q = gray2ind(mat2gray(In_crop), L);
In_q(~nuclei_n_crop) = 0;
% Рассчитать GLCM с несколькими расстояниями и направлениями
dists = [5 7 12 15 20];
offsets = [];
for d = dists
offsets = [offsets; 0 d; -d d; d 0; d d];
end
glcm_sum = zeros(L,L);
for k = 1:size(offsets,1)
off = offsets(k,:);
Mvalid = nuclei_n_crop & circshift(nuclei_n_crop, [-off(1), -off(2)]);
A = In_q; B = circshift(In_q, [-off(1), -off(2)]);
A = A(Mvalid); B = B(Mvalid);
idx = A>=1 & A<=L & B>=1 & B<=L & isfinite(A) & isfinite(B);
if ~any(idx)
continue;
end
A = A(idx); B = B(idx);
M = accumarray([A(:), B(:)], 1, [L L], @sum, 0);
glcm_sum = glcm_sum + M;
end
% Извлечь свойства текстуры
props = graycoprops(glcm_sum, {'Contrast','Homogeneity'});
contrasts(n) = props.Contrast;
homogeneities(n) = props.Homogeneity;
end
Что может вызывать инвертированные значения однородности, и существуют ли альтернативные методы анализа текстуры, которые лучше различают зернистые и однородные ядра на изображениях флуоресцентной микроскопии?
Анализ текстуры с помощью МСУС (матрицы совместного встречания уровней серого) для ядер клеток в флуоресцентной микроскопии действительно может давать контринтуитивные результаты при неправильной реализации. Инвертированные значения однородности, которые вы наблюдаете, вероятно, возникают из-за нескольких проблем в вашем подходе, включая неправильную нормализацию, неоптимальный выбор параметров и возможные артефакты маскирования.
Содержание
- Общие причины инвертированных результатов однородности
- Улучшенная реализация МСУС
- Альтернативные методы анализа текстуры
- Стратегии оптимизации параметров
- Валидация и устранение неполадок
Общие причины инвертированных результатов однородности
Основные проблемы, вызывающие инвертированные значения однородности, вероятно, включают:
-
Неправильная нормализация МСУС: Ваш текущий подход суммирует матрицы МСУС из разных расстояний без надлежащей нормализации, что делает расчет однородности ненадежным.
-
Неоптимальное квантование интенсивности: Использование
mat2gray()с последующим квантованием на 32 уровня может разрушить важные отношения интенсивности в флуоресцентных данных. -
Артефакты маскирования: Установка пикселей, не относящихся к ядрам, в 0 после квантования создает искусственные шаблоны совместного встречания, искажающие измерения текстуры.
-
Неподходящие параметры расстояния: Расстояния [5 7 12 15 20] могут быть слишком большими относительно размера ядер и разрешения изображения.
Улучшенная реализация МСУС
Вот исправленный подход, решающий эти проблемы:
% Рассчитываем количество ядер в изображении
nnuclei = max(In(:));
% Инициализируем векторы для хранения извлеченных данных
intensities = zeros(1, nnuclei);
contrasts = zeros(1, nnuclei);
homogeneities = zeros(1, nnuclei);
entropies = zeros(1, nnuclei); % Дополнительный показатель
% Для каждого ядра в изображении
for n = 1:nnuclei
% Создаем маску для текущего ядра
nuclei_n = (In == n);
% Извлекаем значения флуоресцентной интенсивности
nuclei_n_intensities = Idapi(nuclei_n);
intensities(n) = mean(nuclei_n_intensities);
% Анализ текстуры с использованием МСУС
L = 64; % Увеличенное количество уровней для лучшего разрешения
% Обрезаем область ядра с отступом
[min_row,max_row] = deal(find(any(nuclei_n, 2),1,'first'), find(any(nuclei_n, 2),1,'last'));
[min_col,max_col] = deal(find(any(nuclei_n, 1),1,'first'), find(any(nuclei_n, 1),1,'last'));
padding = 10;
min_row = max(1, min_row-padding);
max_row = min(size(Idapi,1), max_row+padding);
min_col = max(1, min_col-padding);
max_col = min(size(Idapi,2), max_col+padding);
In_crop = Idapi(min_row:max_row, min_col:max_col);
nuclei_n_crop = nuclei_n(min_row:max_row, min_col:max_col);
% Правильно нормализуем интенсивность ядра
nucleus_pixels = In_crop(nuclei_n_crop);
if numel(nucleus_pixels) < 100 % Пропускаем маленькие ядра
contrasts(n) = NaN;
homogeneities(n) = NaN;
entropies(n) = NaN;
continue;
end
% Используем нормализацию на основе квантилей для сохранения отношений интенсивности
p_low = prctile(nucleus_pixels, 5);
p_high = prctile(nucleus_pixels, 95);
In_normalized = (In_crop - p_low) / (p_high - p_low);
In_normalized(In_normalized < 0) = 0;
In_normalized(In_normalized > 1) = 1;
% Квантование с улучшенным методом
In_q = round(In_normalized * (L-1)) + 1;
In_q(~nuclei_n_crop) = 0; % Оставляем фон как 0
% Рассчитываем МСУС с использованием встроенной функции для большей точности
% Используем меньшие расстояния, подходящие для размера ядра
distances = [1, 2, 3]; % Корректируйте в зависимости от разрешения вашего изображения
angles = [0, 45, 90, 135]; % Четыре основных направления
glcm_all = zeros(L, L);
for d = distances
for angle_idx = 1:length(angles)
angle = angles(angle_idx);
% Используем встроенный расчет МСУС
glcm = graycomatrix(In_q, 'Offset', [d*cosd(angle), d*sind(angle)], ...
'NumLevels', L, 'GrayLimits', [0 L-1], ...
'Nhood', 'symmetric');
% Нормализуем эту МСУС
glcm = glcm / sum(glcm(:));
% Взвешиваем по расстоянию (близкие пиксели более важны)
weight = 1 / d;
glcm_all = glcm_all + weight * glcm;
end
end
% Финальная нормализация
glcm_all = glcm_all / sum(glcm_all(:));
% Извлекаем свойства текстуры
props = graycoprops(glcm_all, {'Contrast','Homogeneity','Energy','Entropy'});
contrasts(n) = props.Contrast;
homogeneities(n) = props.Homogeneity;
entropies(n) = props.Entropy; % Добавлена энтропия для дополнительной дискриминации
end
Альтернативные методы анализа текстуры
Когда МСУС дает ненадежные результаты, рассмотрите эти альтернативы:
1. Локальные двоичные шаблоны (LBP)
function lbp_features = calculate_lbp(image, radius, n_points)
% Преобразуем в оттенки серого при необходимости
if size(image, 3) > 1
image = rgb2gray(image);
end
% Расчет LBP
lbp = localbinarypattern(image, n_points, radius, 'uniform');
% Рассчитываем гистограмму
lbp_hist = histcounts(lbp, 0:n_points);
lbp_hist = lbp_hist / sum(lbp_hist); % Нормализуем
% Дополнительные статистики
lbp_features = [mean(lbp), std(lbp), max(lbp_hist), mean(lbp_hist)];
end
2. Матрица длин серых уровней (GLRLM)
function glrlm_features = calculate_glrlm(image, levels)
% Реализация GLRLM для захвата признаков длины пробега
% Особенно хороша для зернистой текстуры
% [Здесь будут детали реализации]
end
3. Многошкальный фрактальный анализ
function fractal_dim = box_counting(image, scales)
% Фрактальная размерность методом подсчета ящиков
% Эффективна для количественной оценки сложности текстуры
% [Здесь будут детали реализации]
end
4. Банк фильтров Габора
function gabor_features = gabor_texture_analysis(image, frequencies, orientations)
% Реакции фильтров Габора для многошкального, многоориентационного анализа текстуры
sigma = 4; % Стандартное отклонение гауссова огибающего
gamma = 0.5; % Пространственное соотношение сторон
gabor_responses = zeros(size(image));
for freq = frequencies
for theta = orientations
% Создаем фильтр Габора
gabor_filter = gabor2d([sigma, sigma], [freq, freq], theta, gamma);
% Применяем фильтр
filtered_img = imfilter(double(image), gabor_filter, 'replicate');
% Сохраняем статистику реакции
gabor_responses = gabor_responses + abs(filtered_img);
end
end
gabor_features = [mean(gabor_responses(:)), std(gabor_responses(:)), ...
max(gabor_responses(:)), mean2(gabor_responses)];
end
Стратегии оптимизации параметров
Для улучшения результатов анализа текстуры:
-
Оптимизация расстояния: Рассчитайте средний диаметр ядра и используйте расстояния, составляющие 5-10% от этого диаметра.
-
Анализ углов: Проверьте, улучшит ли использование всех 8 направлений (0°, 45°, 90°, 135°, 180°, 225°, 270°, 315°) результаты.
-
Выбор уровней: Экспериментируйте с разными уровнями квантования (32, 64, 128) и используйте тот, который лучше сохраняет отношения интенсивности.
-
Методы нормализации: Сравните разные подходы к нормализации:
- На основе квантилей (как показано в улучшенном коде)
- Масштабирование min-max
- Нормализация по z-оценке
Валидация и устранение неполадок
Чтобы убедиться, что ваш анализ текстуры работает правильно:
-
Визуальная валидация: Создайте карты текстуры, накладывая их на исходные изображения, для визуальной проверки результатов.
-
Контрольные эксперименты: Протестируйте с известными однородными и зернистыми образцами для установления базовых значений.
-
Статистическая валидация: Используйте статистические тесты (t-тесты, ANOVA) для подтверждения значимых различий между типами ядер.
-
Корреляция признаков: Проверьте корреляции между различными метриками текстуры для выявления избыточности.
-
Снижение размерности: Примените PCA или t-SNE для визуализации того, насколько хорошо ваши признаки разделяют разные типы ядер.
Ключом к успешному анализу текстуры в флуоресцентной микроскопии является понимание того, что однородность должна уменьшаться по мере усложнения текстуры. Если вы наблюдаете обратное, это почти всегда связано с проблемами реализации, а не с биологической реальностью. Улучшенная реализация выше решает наиболее распространенные ловушки, предоставляя при этом дополнительные метрики для лучшей дискриминации между зернистыми и однородными ядрами.