ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

MapReduce フレームワークと Hadoop を使用した大規模なイメージ セットの処理

この例では、Image Processing Toolbox™ とともに MATLAB® の MapReduce および Datastore を使用して、大量のイメージに細胞カウント アルゴリズムを実行する方法を説明します。MapReduce とは、メモリに収まらないデータセットを解析するプログラミング手法です。また、この例では MATLAB Distributed Computing Server™ を使用して並列 MapReduce プログラムを Hadoop® クラスターで実行します。この例では、アルゴリズムをローカル システムでテストしてから Hadoop クラスターに移行できるように、イメージのサブセットを作成する方法を説明します。

サンプル データのダウンロード

この例の部分では、Broad Bioimage Benchmark Collection から BBBC005v1 データセットをダウンロードする方法を説明します。このデータセットはテストや検証のために作られている注釈の付いた生体イメージ セットです。このイメージ セットでは合焦点および焦点外の合成イメージの例が提供されており、フォーカス メトリクスの検証に使用できます。データセットには約 2 万ファイルが格納されています。詳細については、こちらの Introduction to the Data Set を参照してください。

Linux システムのシステム プロンプトで wget コマンドを使用し、BBBC データセットを格納している zip ファイルをダウンロードします。このコマンドを実行する前に、zip ファイル (1.8 GB) と解凍したイメージ (2.6 GB) を十分保持できるスペースがターゲットの場所にあることを確認してください。

wget http://www.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 倍のガウス ローパス フィルターでフィルター処理された (F1) ことを示しています。w1 は使用された染色を識別します。

イメージ ファイルの表示とアルゴリズムのテスト

この例では、イメージのバッチ処理アプリを使用して BBBC データセット内のファイルを表示し、少量のファイルのサブセットでアルゴリズムをテストする方法を説明します。この例はイメージ内の細胞をセグメント化する簡単なアルゴリズムをテストします (この例では、この細胞セグメンテーション アルゴリズムを変更したバージョンを使用して、MapReduce の実装で使用する細胞カウント アルゴリズムを作成します)。

イメージのバッチ処理アプリを開きます。MATLAB ツールストリップの [アプリ] タブにある [画像処理とコンピューター ビジョン] グループで [イメージのバッチ処理] をクリックします。imageBatchProcessor コマンドを使用して、コマンド ラインからアプリを開くこともできます。

細胞のイメージ データセットをアプリに読み込みます。イメージのバッチ処理アプリで、[イメージの読み込み] をクリックし、ダウンロードしたデータセットが格納されているフォルダーに移動します。

細胞セグメンテーション アルゴリズムを実装する関数の名前を指定します。既存の関数を指定するには、[関数名] フィールドに名前を入力するか、フォルダー アイコンをクリックして参照し、関数を選択します。新しいバッチ処理関数を作成するには、[新規] をクリックし、MATLAB エディターで開いたテンプレート ファイルにコードを入力します。この例では、以下のイメージ セグメンテーション コードを含む新しい関数を作成します。

function imout = cellSegmenter(im)
% A simple cell segmenter

% Otsu thresholding
t  = graythresh(im);
bw = im2bw(im,t);

% 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);
18

18

アプリに表示されるイメージをいくつかマウスで選択し、[実行] をクリックしてアルゴリズムのテストを実行します。

メモ

この例では、染色が w1 のイメージのみを選択します。セグメンテーション アルゴリズムはこれらのイメージに最適です。

アルゴリズムの実行結果を調べ、セグメンテーション アルゴリズムでイメージ内の細胞の数が正確に検出されたことを確認します。イメージの名前には C の数字により細胞数が示されています。たとえば、SIMCEPImages_A05_C18_F1_s05_w1.TIF という名前のイメージには 18 個の細胞が含まれています。この個数とコマンド ラインに返された両方のイメージの結果を比較します。

MapReduce フレームワークのローカル テスト: データの準備

この例では、大規模な処理の実行にあたり、小規模なテスト バージョンをローカル システムで設定する方法を説明します。大量のファイルで実行する前に、処理フレームワークをテストする必要があります。これを行うには、まずイメージを格納するイメージ データ ストアを作成しなければなりません。MapReduce は、データ ストアを使用して、メモリに収まる小さいチャンクごとにデータを処理します。ローカルのテストでは、開発プロセスを反復的にして短縮できるように、データストアのイメージのサブセットを選択します。データストアを作成したら、イメージのサブセットのサンプルを、Hadoop クラスターで使用される形式である Hadoop シーケンス ファイルに変換します。

ImageDatastore を作成します。cellSegmenter.m に実装される細胞セグメンテーション アルゴリズムは細胞体染色で最適に機能するため、ファイル名のインジケーターが w1 のファイルのみを選択します。

localDataFolder = '/your_data/broad_data/BBBC005_v1_images/';
w1FilesOnly     = fullfile(localDataFolder,'*w1*');
localimds       = imageDatastore(w1FilesOnly);
disp(localimds);
 ImageDatastore with properties:

      Files: {
             ' .../broad_data/BBBC005_v1_images/SIMCEPImages_A01_C1_F1_s01_w1.TIF';
             ' .../broad_data/BBBC005_v1_images/SIMCEPImages_A01_C1_F1_s02_w1.TIF';
             ' .../broad_data/BBBC005_v1_images/SIMCEPImages_A01_C1_F1_s03_w1.TIF'
              ... and 9597 more
             }
    ReadFcn: @readDatastoreImage

サブセットには、まだ 9000 以上のファイルが存在します。

データセットに含まれる大量のファイルから 100 個ごとにファイルを選択し、サンプルのサブセットを絞り込みます。これによりファイルの数は処理しやすい数まで減少します。

localimds.Files = localimds.Files(1:100:end);
disp(localimds);
ImageDatastore with properties:

      Files: {
             ' .../broad_data/BBBC005_v1_images/SIMCEPImages_A01_C1_F1_s01_w1.TIF';
             ' .../broad_data/BBBC005_v1_images/SIMCEPImages_A05_C18_F1_s01_w1.TIF';
             ' .../broad_data/BBBC005_v1_images/SIMCEPImages_A09_C35_F1_s01_w1.TIF'
              ... and 93 more
             }
    ReadFcn: @readDatastoreImage

イメージのサブセットを Hadoop シーケンス ファイルに再パッケージ化します。この手順は、あるストレージ形式から別の形式にデータを変更するだけでデータ値は変更されません。シーケンス ファイルの詳細については、MapReduce 入門 (MATLAB)を参照してください。

MATLAB 関数 mapreduce を使用してこの変換を行うことができます。関数 mapreduce に渡す "map" 関数と "reduce" 関数を作成しなければなりません。イメージ ファイルを Hadoop シーケンス ファイルに変換するには、map 関数をノーオペレーション関数にする必要があります。この例では、map 関数はファイル名をキーとして使用し、イメージ データをそのまま単純に保存します。

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

reduce 関数を作成します。この関数は、イメージ ファイルをシーケンス ファイルのキーと値のデータストアに変換します。

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

mapreduce を呼び出し、map 関数と reduce 関数を渡します。この例では、まず関数 mapreducer を呼び出し、処理の場所を指定します。ローカル システムで設定をテストして処理を実行するには、0 を指定します(ローカルで実行すると、mapreduce は MAT ファイルのキーと値のデータストアを作成します)。次のコードの関数 mapreducer はローカル システムで処理を行う指定になっています。

mapreducer(0);

matFolder = 'BBBC005_v1_subset_images_w1_mat';
localmatds = mapreduce(localimds, ...
    @identityMap, @identityReduce,...
    'OutputFolder', matFolder);
disp(localmatds);
********************************
*      MAPREDUCE PROGRESS      *
********************************
Map   0% Reduce   0%
Map  10% Reduce   0%
Map  20% Reduce   0%
Map  30% Reduce   0%
Map  40% Reduce   0%
Map  50% Reduce   0%
Map  60% Reduce   0%
Map  70% Reduce   0%
Map  80% Reduce   0%
Map  90% Reduce   0%
Map 100% Reduce   0%
Map 100% Reduce  10%
Map 100% Reduce  20%
Map 100% Reduce  30%
Map 100% Reduce  40%
Map 100% Reduce  50%
Map 100% Reduce  60%
Map 100% Reduce  70%
Map 100% Reduce  80%
Map 100% Reduce  90%
Map 100% Reduce 100%
  KeyValueDatastore with properties:

       Files: {
              ' .../results_1_12-Jun-2015_10-41-25_187.mat';
              ' .../results_2_12-Jun-2015_10-41-25_187.mat'
              }
    ReadSize: 1 key-value pairs
    FileType: 'mat'

MapReduce フレームワークのローカル テスト: アルゴリズムの実行

この例では、MapReduce フレームワークをローカル システムでテストする方法を説明します。イメージ ファイルのサブセットをテスト用に作成し、キーと値のデータストアに変換したら、いつでもアルゴリズムをテストできます。元の細胞セグメンテーション アルゴリズムを、細胞数を返すように変更します(この例で最初にアルゴリズムをテストした、イメージのバッチ処理アプリは、処理されたイメージのみを返し、細胞数などの値を返すことができません)。

細胞数を返すように、細胞セグメンテーション関数を変更します。

function cellCount = cellCounter(im)
% A simple cell counter

% Otsu thresholding
t  = graythresh(im);
bw = im2bw(im,t);

% Show thresholding result in app
% imout = imfuse(im,bw);

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));

必要な処理を実行するための map 関数と reduce 関数を作成します。この例では、特定のイメージのエラー数を計算する map 関数を作成します。この関数はファイル名のコーディング (C の数字) からイメージの実際の細胞数を取得し、セグメンテーション アルゴリズムで返された細胞数と比較します。

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

フォーカス値ごとに細胞数のエラー平均値を計算する reduce 関数を作成します。

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, focusBlur, meanDiff);
end

mapreduce ジョブをローカル システムで実行します。

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

% Gather the result
focusErrorTbl = readall(focusErrords);
disp(focusErrorTbl);
averageErrors = cell2mat(focusErrorTbl.Value);
********************************
*      MAPREDUCE PROGRESS      *
********************************
Map   0% Reduce   0%
Map  10% Reduce   0%
Map  20% Reduce   0%
Map  30% Reduce   0%
Map  40% Reduce   0%
Map  50% Reduce   0%
Map  75% Reduce   0%
Map 100% Reduce   0%
Map 100% Reduce  13%
Map 100% Reduce  25%
Map 100% Reduce  38%
Map 100% Reduce  50%
Map 100% Reduce  63%
Map 100% Reduce  75%
Map 100% Reduce  88%
Map 100% Reduce 100%
    Key      Value  
    ___    _________

     1     [ 0.8333]
     4     [ 0.6667]
     7     [ 0.5000]
    10     [ 0.5000]
    14     [ 0.5000]
    17     [ 0.5000]
    20     [ 0.5000]
    23     [ 0.3333]
    26     [ 0.8333]
    29     [ 0.8333]
    32     [      3]
    35     [      7]
    39     [12.3333]
    42     [17.3333]
    45     [18.3333]
    48     [23.8333]

サブセットの結果を検査します。ここで使用する簡単な細胞カウント アルゴリズムは、細胞または細胞群の平均の面積に依存します。焦点のブレが大きくなると、細胞の境界が拡散するため、面積も広がります。焦点のブレが大きくなると、誤差が増加するという結果が予測されます。結果をプロットします。

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');

Hadoop クラスターでの MapReduce フレームワークの実行

この例では、すべてのイメージ データを Hadoop ファイル システムに読み込み、MapReduce フレームワークを Hadoop クラスターで実行する方法を説明します。

次のシェル コマンドを使用してイメージ データを Hadoop ファイル システムに読み込みます。

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

MATLAB Distributed Computing Server クラスターへのアクセスを設定します。

setenv('HADOOP_HOME', '/mathworks/AH/hub/apps_PCT/LS_Hadoop_hadoop01glnxa64/hadoop-2.5.1/');
cluster = parallel.cluster.Hadoop;
cluster.HadoopProperties('mapred.job.tracker') = 'hadoop01glnxa64:54311';
cluster.HadoopProperties('fs.default.name') = 'hdfs://hadoop01glnxa64:54310';
disp(cluster);
% Change mapreduce execution environment to point to the remote cluster
mapreducer(cluster);
Hadoop with properties:

                 HadoopInstallFolder: '/your_data/apps_PCT/LS_Hadoo...'
             HadoopConfigurationFile: ''
                    HadoopProperties: [2x1 containers.Map]
                   ClusterMatlabRoot: '/your_cluster...'
    RequiresMathWorksHostedLicensing: 0
                       LicenseNumber: ''
                     AutoAttachFiles: 1
                       AttachedFiles: {}
                     AdditionalPaths: {}

すべてのイメージ データを Hadoop シーケンス ファイルに変換します。これは、プロトタイピング用のイメージのサブセットを変換したときにローカル システムで実行した内容と同様のものです。前に使用した map 関数と reduce 関数を再利用できます。

% Use the internal Hadoop cluster ingested with Broad Institute files
broadFolder = 'hdfs://hadoop01glnxa64:54310/user/broad_data/BBBC005_v1_images';

% Pick only the 'cell body stain' (w1) files for processing
w1Files = fullfile(broadFolder, '*w1*.TIF');

% Create an ImageDatastore representing all these files
imageDS = imageDatastore(w1Files);

% Specify the output folder.
seqFolder = 'hdfs://hadoop01glnxa64:54310/user/datasets/images/broad_data/broad_sequence';

% Convert the images to a key-value datastore.
seqds = mapreduce(imageDS, @identityMap, @identityReduce,'OutputFolder', seqFolder); 

MapReduce フレームワークを使用して、Hadoop ファイル システムに格納されたデータセット全体に細胞カウント アルゴリズムを実行します。ローカル バージョンと唯一異なる点は、入力と出力の場所が Hadoop ファイル システム上にあることです。

% Output location for error count.
output = 'hdfs://hadoop01glnxa64:54310/user/broad_data/BBBC005_focus_vs_errorCount';
tic;
focusErrords = mapreduce(seqds, @mapImageToMisCountError, @reduceErrorCount,...
    'OutputFolder',output);
toc
% Gather result
focusErrorTbl = readall(focusErrords);
disp(focusErrorTbl);
averageErrors = cell2mat(focusErrorTbl.Value);

% Plot
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');
Parallel mapreduce execution on the Hadoop cluster:
********************************
*      MAPREDUCE PROGRESS      *
********************************
Map   0% Reduce   0%
Map   7% Reduce   0%
Map  10% Reduce   0%
Map  12% Reduce   0%
Map  20% Reduce   0%
Map  23% Reduce   0%
Map  25% Reduce   0%
Map  28% Reduce   0%
Map  30% Reduce   0%
Map  32% Reduce   0%
Map  33% Reduce   0%
Map  38% Reduce   0%
Map  41% Reduce   0%
Map  43% Reduce   0%
Map  48% Reduce   0%
Map  50% Reduce   0%
Map  51% Reduce   5%
Map  53% Reduce   7%
Map  55% Reduce  10%
Map  56% Reduce  11%
Map  58% Reduce  11%
Map  62% Reduce  12%
Map  64% Reduce  12%
Map  65% Reduce  12%
Map  67% Reduce  16%
Map  69% Reduce  16%
Map  71% Reduce  16%
Map  74% Reduce  17%
Map  75% Reduce  17%
Map  76% Reduce  17%
Map  79% Reduce  20%
Map  83% Reduce  23%
Map  85% Reduce  24%
Map  88% Reduce  24%
Map  92% Reduce  24%
Map  94% Reduce  25%
Map  96% Reduce  28%
Map  97% Reduce  29%
Map 100% Reduce  66%
Map 100% Reduce  69%
Map 100% Reduce  78%
Map 100% Reduce  87%
Map 100% Reduce  96%
Map 100% Reduce 100%
Elapsed time is 227.508109 seconds.
    Key      Value  
    ___    _________

     4     [ 1.1117]
     7     [ 1.0983]
    10     [ 1.0500]
    14     [ 0.9317]
    17     [ 0.8650]
    20     [ 0.7583]
    23     [ 0.6050]
    26     [ 1.0600]
    29     [ 1.5750]
    32     [ 4.0633]
    42     [18.9267]
    48     [26.2417]
     1     [ 1.0083]
    35     [ 7.5650]
    39     [13.2383]
    45     [20.5500]

参考

|

関連するトピック