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

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

Загрузка выборочных данных

Загрузите набор BBBC005v1 данных из Broad Bioimage Benchmark Collection. Этот набор данных представляет собой аннотированный набор биологических изображений, предназначенный для проверки и валидации. Набор изображений предоставляет примеры синтетических изображений внутри и вне фокуса, которые могут использоваться для валидации метрик особого внимания. Набор данных содержит почти 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). The w1 определяет используемое пятно. Например, найдите количество изображений в наборе данных, которые используют w1 пятно.

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

Загрузка файлов изображений в Image Batch Processor

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

Откройте приложение Image Batch Processor. На панели инструментов MATLAB, на вкладке Apps, в разделе Image Processing and Компьютерное Зрение, нажмите Image Batch Processor. Открыть приложение из командной строки можно также с помощью imageBatchProcessor команда.

В приложении Image Batch Processor нажмите Загрузить изображения и перейдите к папке, в которой вы хранили загруженный набор данных.

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

Задайте функцию сегментации

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

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

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

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

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

Протестируйте своя среда локально

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

Сначала создайте изображение datastore, используя ImageDatastore функция, содержащая небольшое подмножество ваших изображений. MapReduce использует datastore для обработки данных маленькими фрагментами, которые индивидуально помещаются в память. Перейдите в папку, содержащую изображения, и создайте datastore. Потому что алгоритм сегментации камеры реализован в 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

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

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

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

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

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

Функции mapreduce, передача вашей карты и сокращение функций. Пример сначала вызывает mapreducer функция для определения места выполнения обработки. Чтобы протестировать настройку и выполнить обработку в локальной системе, задайте 0.

mapreducer(0);

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

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

Протестируйте своя среда локально

После создания подмножества файлов изображений для проверки и преобразования их в key-value datastore, вы готовы протестировать алгоритм. Измените свой исходный алгоритм сегментации камер, чтобы вернуть количество камер. (Приложение Image Batch Processor, где этот пример впервые протестировал алгоритм, может возвращать только обработанные изображения, а не значения, такие как количество камер.)

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

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

Создайте функцию map, которая вычисляет количество ошибок для определенного изображения. Эта функция получает фактическое количество камер для изображения из имени файла, кодирующего (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 Parallel Server

Настройка доступа к кластеру MATLAB Parallel Server. Чтобы запустить эту команду, замените '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);

Измените Mapreduce Выполнения Окружения на удаленный кластер

Измените 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';

Преобразуйте изображения в datastore с ключевым значением.

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

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

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

Во-первых, укажите выходное расположение для счетчика ошибок.

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

Запустите алгоритм на среде Mapreduce. Используйте 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

См. также

|

Похожие темы