exponenta event banner

Обработка большого набора изображений с помощью MapReduce Framework и Hadoop

В этом примере показано, как выполнить алгоритм подсчета ячеек для большого количества изображений с помощью инструментария обработки изображений с помощью MATLAB ® MapReduce и Datastore. MapReduce - метод программирования для анализа наборов данных, не вписывающихся в память. В примере также используется Server™ MATLAB Parallel для запуска параллельных программ MapReduce на кластерах Hadoop ®. В примере показано, как протестировать алгоритм в локальной системе на подмножестве образов перед перемещением в кластер Hadoop.

Загрузить образец данных

Загрузите BBBC005v1 набор данных из коллекции Benchmark Broad Bioimage. Этот набор данных представляет собой аннотированный набор биологических изображений, предназначенный для тестирования и проверки. Набор изображений предоставляет примеры синтетических изображений в фокусе и вне фокуса, которые могут использоваться для проверки метрик фокуса. Набор данных содержит почти 20 000 файлов. Дополнительные сведения см. в разделе Введение в набор данных.

В командной строке системы Linux используйте wget для загрузки zip-файла, содержащего набор данных BBBC. Перед выполнением этой команды убедитесь, что в целевом расположении достаточно места для хранения zip-файла (1,8 ГБ) и извлеченных образов (2,6 ГБ).

wget https://data.broadinstitute.org/bbbc/BBBC005/BBBC005_v1_images.zip

По запросу системы Linux извлеките файлы из zip-файла.

unzip BBBC005_v1_images.zip

Проверьте имена файлов изображений в этом наборе данных. Имена создаются в определенном формате и содержат полезную информацию о каждом изображении. Например, имя файла BBBC005_v1_images/SIMCEPImages_A05_C18_F1_s16_w1.TIF указывает, что изображение содержит 18 ячеек (C18) и был отфильтрован гауссовым фильтром нижних частот диаметром 1 и сигмой диаметром 0,25 x для моделирования размывания фокуса (F1). w1 определяет используемое пятно. Например, найдите количество изображений в наборе данных, которые используют w1 пятно.

d = dir('C:\Temp\BBBCdata\BBBC005_v1_images\*w1*');
numel(d)
ans = 9600

Загрузка файлов изображений в процессор пакетной обработки изображений

Просмотрите файлы в наборе данных BBBC и протестируйте алгоритм для небольшого подмножества файлов с помощью приложения «Процессор пакетной обработки изображений». Пример проверяет простой алгоритм, который сегментирует ячейки на изображениях. (В примере используется модифицированная версия этого алгоритма сегментации ячеек для создания алгоритма подсчета ячеек, используемого в реализации MapReduce.)

Откройте приложение Процессор пакетной обработки изображений. На панели инструментов MATLAB на вкладке Приложения в разделе Обработка изображений и компьютерное видение щелкните Процессор пакетной обработки изображений. Вы также можете открыть приложение из командной строки с помощью imageBatchProcessor команда.

В приложении Процессор пакетной обработки изображений щелкните Загрузить изображения и перейдите в папку, в которой был сохранен загруженный набор данных.

Приложение «Процессор пакетной обработки изображений» отображает миниатюры изображений в папке на левой панели и версию выбранного изображения с более высоким разрешением на вкладке «Входное изображение». Просмотрите некоторые изображения, чтобы ознакомиться с набором данных.

Определение функции сегментации

Укажите имя функции, реализующей алгоритм сегментации ячеек. Чтобы указать существующую функцию, введите ее имя в поле Имя функции или щелкните значок папки, чтобы просмотреть и выбрать функцию. Для создания новой функции пакетной обработки щелкните Создать. Приложение открывает шаблон пакетной функции в редакторе MATLAB ®. В этом примере создайте новую функцию, содержащую следующий код сегментации изображения. Щелкните Сохранить, чтобы создать пакетную функцию. Приложение обновляется для отображения имени функции, созданной в разделе «Пакетная функция» панели инструментов приложения.

function imout = cellSegmenter(im)  % A simple cell segmenter 
    % Otsu thresholding
    bw = imbinarize(im);
    
    % Show thresholding result in app
    imout = imfuse(im,bw);
    
    % Find area of blobs
    stats = regionprops('table',bw,{'Area'});
    
    % Average cell diameter is about 33 pixels (based on random inspection)
    cellArea = pi*(33/2)^2;
    
    % Estimate cell count based on area of blobs
    cellsPerBlob = stats.Area/cellArea;
    cellCount = sum(round(cellsPerBlob));
    disp(cellCount);
end

Протестируйте функцию сегментации на образце изображения

Выберите миниатюру изображения, отображаемого в приложении, и нажмите Обработать выбранные, чтобы выполнить тестовый запуск алгоритма. В этом примере выберите только изображение с помощью "w1"stain (идентифицируется в имени файла). Алгоритм сегментации лучше всего работает с этими изображениями.

Проверьте результаты выполнения алгоритма, чтобы убедиться, что алгоритм сегментации обнаружил правильное количество ячеек в изображении. Имена изображений содержат число ячеек в C номер. Например, изображение с именем SIMCEPImages_A05_C18_F1_s05_w1.TIF содержит 18 ячеек. Сравните это число с результатами, полученными в командной строке образца изображения.

Локальное тестирование MapReduce Framework

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

Сначала создайте хранилище данных образа с помощью ImageDatastore функция, содержащая небольшое подмножество изображений. MapReduce использует хранилище данных для обработки данных в небольших фрагментах, которые по отдельности вписываются в память. Перейдите в папку, содержащую изображения, и создайте хранилище данных изображений. Потому что алгоритм сегментации ячеек реализован в cellSegmenter.m лучше всего работает с пятном тела клетки, выберите только файлы с индикатором w1 в именах файлов.

localimds = imageDatastore(fullfile('/your_data/broad_data/BBBC005_v1-images','*w1*'));

Даже ограничение выбора файлом с "w1"в их именах хранилище данных изображения по-прежнему содержит более 9000 файлов. Далее подбирайте список изображений, выбирая каждый 100-й файл из тысяч файлов в наборе данных.

localimds.Files = localimds.Files(1:100:end);

Переупаковка набора образцов в файл последовательности Hadoop

После создания хранилища данных изображения преобразуйте образец подмножества изображений в файлы последовательности Hadoop, формат, используемый кластером Hadoop. Обратите внимание, что на этом этапе данные просто изменяются из одного формата хранения в другой без изменения значения данных. Дополнительные сведения о файлах последовательности см. в разделе Начало работы с MapReduce (MATLAB).

Чтобы преобразовать хранилище данных изображения в файл последовательности Hadoop, создайте функцию «map» и функцию «reduct», которую вы передаете mapreduce функция. Для преобразования файлов изображений в файлы последовательности Hadoop функция отображения должна быть функцией no-op. В этом примере функция отображения просто сохраняет данные изображения как есть, используя имя файла в качестве ключа.

function identityMap(data, info, intermKVStore)
     add(intermKVStore, info.Filename, data);
end

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

function identityReduce(key, intermValueIter, outKVStore)
    while hasnext(intermValueIter)
        add(outKVStore, key, getnext(intermValueIter));
    end
end

Звонить mapreduce, прохождение карты и сокращение функций. В примере сначала вызывается mapreducer для указания места обработки. Для тестирования настройки и выполнения обработки в локальной системе укажите 0.

mapreducer(0);

При локальном запуске mapreduce создает хранилище данных с ключевым значением, поддерживаемое MAT-файлами.

localmatds = mapreduce(localimds, @identityMap, @identityReduce,'OutputFolder', pwd);

Локальное тестирование MapReduce Framework

После создания подмножества файлов изображений для тестирования и преобразования их в хранилище данных с ключевым значением можно протестировать алгоритм. Измените исходный алгоритм сегментации ячеек, чтобы вернуть количество ячеек. (Приложение «Процессор пакетной обработки изображений», в котором этот пример впервые протестировал алгоритм, может возвращать только обработанные изображения, а не такие значения, как количество ячеек.)

Измените функцию сегментации ячеек, чтобы вернуть количество ячеек и удалить отображение изображения.

function cellCount = cellCounter(im)
    % Otsu thresholding
    bw = imbinarize(im);
   
    % Find area of blobs
    stats = regionprops('table',bw,{'Area'});
    
    % Average cell diameter is about 33 pixels (based on random inspection)
    cellArea = pi*(33/2)^2;
    
    % Estimate cell count based on area of blobs
    cellsPerBlob = stats.Area/cellArea;
    cellCount = sum(round(cellsPerBlob));
end

Создайте функцию сопоставления, которая вычисляет количество ошибок для определенного изображения. Эта функция получает фактическое количество ячеек для изображения из кодировки имени файла ( C number) и сравнивает его с количеством ячеек, возвращенным алгоритмом сегментации.

function mapImageToMisCountError(data, ~, intermKVStore)
    % Extract the image
    im = data.Value{1};
    % Call the cell counting algorithm
    actCount = cellCounter(im);
    % The original file name is available as the key
    fileName = data.Key{1};
    [~, name] = fileparts(fileName);
    % Extract expected cell count and focus blur from the file name
    strs = strsplit(name, '_'); 
    expCount  = str2double(strs{3}(2:end)); 
    focusBlur = str2double(strs{4}(2:end)); 
    diffCount = abs(actCount-expCount);
    % Note: focus blur is the key 
    add(intermKVStore, focusBlur, diffCount);
end

Создайте функцию уменьшения, которая вычисляет среднюю ошибку в количестве ячеек для каждого значения фокуса.

function reduceErrorCount(key, intermValueIter, outKVStore)
    focusBlur = key;
    % Compute the sum of all differences in cell count for this value of
    % focus blur
    count = 0;
    totalDiff = 0;
    while hasnext(intermValueIter)
        diffCount = getnext(intermvalueIter);
        count = count + 1;
        totalDiff = totalDiff+diffCount;
    end
    % Average
    meanDiff = totalDiff/count;
    add(outKVStore, focusBlue, meanDiff);
end

Запустить mapreduce задание в локальной системе.

focusErrords = mapreduce(localmatds, @mapImageToMisCountError, @reduceErrorCount);

Соберите результаты.

focusErrorTbl = readall(focusErrords);

Получение средних значений ошибок.

averageErrors = cell2mat(focusErrorTbl.Value);

Используемый здесь простой алгоритм подсчета ячеек основан на средней площади ячейки или группы ячеек. Увеличивающееся размытие фокуса диффундирует границы ячеек и, таким образом, площадь. Ожидаемый результат состоит в том, что ошибка будет возрастать с увеличением размытия фокуса, как видно на этом графике результатов.

function plot_errors()
bar(focusErrorTbl.Key, averageErrors);
ha = gca;
ha.XTick = sort(focusErrorTbl.Key);
ha.XLim  = [min(focusErrorTbl.Key)-2 max(focusErrorTbl.Key)+2];
title('Cell counting result on a test data set');
xlabel('Focus blur');
ylabel('Average error in cell count');
end

Запуск MapReduce Framework на кластере Hadoop

После проверки обработки алгоритма для подмножества данных запустите алгоритм для полного набора данных в кластере Hadoop.

Загрузка данных в файловую систему Hadoop

Загрузите все данные изображения в файловую систему Hadoop и запустите инфраструктуру MapReduce в кластере Hadoop с помощью следующих команд оболочки. Чтобы выполнить эту команду, замените your_data с расположением на компьютере.

hadoop fs -mkdir /user/broad_data/

hadoop fs -copyFromLocal /your_data/broad_data/BBBC005_v1_images /user/broad_data/BBBC005_v1_images

Настройка доступа к кластеру параллельных серверов MATLAB

Настройка доступа к кластеру параллельного сервера MATLAB. Чтобы выполнить эту команду, замените 'your/hadoop/install' с расположением на компьютере.

setenv('HADOOP_HOME','/your/hadoop/install');

cluster = parallel.cluster.Hadoop;

cluster.HadoopProperties('mapred.job.tracker') = 'hadoop01glnxa64:54311';

cluster.HadoopProperties('fs.default.name') = 'hdfs://hadoop01glnxa64:54310';

disp(cluster);

Изменение среды выполнения Mapreduction на удаленный кластер

Изменить mapreduce для указания на удаленный кластер.

mapreducer(cluster);

Преобразовать все данные изображения в файлы последовательности Hadoop

Преобразование всех данных изображения в файлы последовательности Hadoop. Это аналогично тому, что было сделано в локальной системе при преобразовании подмножества образов для прототипирования. Можно повторно использовать карту и сократить ранее использовавшиеся функции. Используйте внутренний кластер Hadoop.

broadFolder = 'hdfs://hadoop01glnxa64:54310/user/broad_data/BBBC005_v1_images';

Выберите только файлы пятен тела ячейки (w1) для обработки.

w1Files = fullfile(broadFolder, '*w1*.TIF');

Создание ImageDatastore представление всех этих файлов

imageDS = imageDatastore(w1Files);

Укажите папку вывода.

seqFolder = 'hdfs://hadoop01glnxa64:54310/user/datasets/images/broad_data/broad_sequence';

Преобразование изображений в хранилище данных с ключевым значением.

seqds = mapreduce(imageDS, @identityMap, @identityReduce,'OutputFolder', seqFolder);

Запустить алгоритм подсчета ячеек для всего набора данных

Запустите алгоритм подсчета ячеек для всего набора данных, хранящегося в файловой системе Hadoop, с помощью платформы MapReduce. Единственное изменение от запуска платформы в локальной системе заключается в том, что теперь расположения ввода и вывода находятся в файловой системе Hadoop.

Сначала укажите местоположение вывода для подсчета ошибок.

output = 'hdfs://hadoop01glnxa64:54310/user/broad_data/BBBC005_focus_vs_errorCount';

Запустите алгоритм на платформе Mapreduction. Используйте tic и toc для записи времени обработки набора изображений.

tic;

focusErrords = mapreduce(seqds, @mapImageToMisCountError, @reduceErrorCount,'OutputFolder',output);

toc

Соберите результаты.

focusErrorTbl = readall(focusErrords);

averageErrors = cell2mat(focusErrorTbl.Value);

Постройте график результатов, как и раньше.

function reduceErrorCountAll(key, intermValueIter, outKVStore)
    bar(focusErrorTbl.Key, averageErrors);
    ha = gca;
    ha.XTick = sort(focusErrorTbl.Key);
    ha.XLim  = [min(focusErrorTbl.Key)-2 max(focusErrorTbl.Key)+2];
    title('Cell counting result on the entire data set');
    xlabel('Focus blur');
    ylabel('Average error in cell count');
end

См. также

|

Связанные темы