ブロックのサイズとパフォーマンス
関数 blockproc
を使用してイメージ ファイルを読み取ったり書き込んだりすると、ファイルにアクセスする回数によってパフォーマンスが大きな影響を受けます。一般的に、大きなブロック サイズを選択すると各ブロックを処理するためのメモリが増えるため、blockproc
がディスクにアクセスする回数が減ります。ディスク上のファイル形式のレイアウトを把握しておくと、ディスクにアクセスする回数を最小限にするブロック サイズを選択するのに役立ちます。
TIFF イメージの特性
TIFF イメージでは、ディスク上のデータはタイルまたはストリップのいずれかで構成されています。タイル配置された TIFF イメージは、ファイル内に四角形ブロックのデータを連続して格納します。各タイルは 1 つの単位として読み書きされます。ストリップ レイアウトの TIFF イメージはデータをストリップに格納します。つまり、各ストリップの幅はイメージの幅全体になり、高さは 1 行以上です。(ストリップの TIFF イメージは常に行でまとめられ、列でまとめられていることはありません)。タイルと同様に、各ストリップは 1 つの単位として格納され、読み書きされます。
TIFF イメージ処理に適切なブロック サイズを選択するときは、TIFF イメージの構成を理解することが重要です。イメージがタイルまたはストリップのどちらで構成されているかを調べるには、関数 imfinfo
を使用します。
TIFF イメージについて imfinfo
が返した構造体には、TileWidth
フィールドおよび TileLength
フィールドが含まれています。これらのフィールドに有効な (空でない) 値が含まれている場合、イメージはタイル配置された TIFF であり、これらのフィールドにより各タイルのサイズが定義されています。これらのフィールドに空の ([]
) 値が含まれている場合、TIFF はストリップで構成されています。ストリップ レイアウトの TIFF の場合は、構造体の RowsPerStrip
フィールドを参照します。ここでは、データの各ストリップのサイズが定義されています。
TIFF イメージを読み取るとき、読み取り可能なデータの最小量は、TIFF のタイプによって、1 タイルまたは 1 ストリップです。blockproc
のパフォーマンスを最適化するには、ディスク上での TIFF イメージの構成に対応するブロック サイズを選択します。こうすると、同じピクセルを何度も読み取らずにすみます。
ブロック サイズの選択による blockproc パフォーマンスの最適化
この例では、blockproc
のパフォーマンスにブロック サイズがどう影響するかを説明します。これらのケースでは、各ブロック内のピクセル総数はほぼ同じです。ブロックの寸法のみが異なります。
イメージ ファイルを読み取って TIFF ファイルに変換します。
I = imread('concordorthophoto.png','PNG'); imshow(I)
imwrite(I,'concordorthophoto.tif','TIFF');
imfinfo
を使用して、concordorthophoto.tif
がストリップまたはタイルのどちらで構成されているかを調べます。info
構造体の RowsPerStrip
フィールドは、この TIFF イメージが高さ 34 行のストリップで構成されていることを示します。各ストリップの幅はイメージの幅で、高さは 34 ピクセルです。
info = imfinfo('concordorthophoto.tif');
info.RowsPerStrip
ans = 34
info
の Height
フィールドおよび Width
フィールドからイメージ サイズを取得します。このイメージのサイズは 2215 x 2956 ピクセルです。
h = info.Height
h = 2215
w = info.Width
w = 2956
ケース 1: 正方形ブロック
サイズが 500 x 500 ピクセルの正方形ブロックを使用して、イメージを処理します。関数 blockproc
がディスクにアクセスするたびにストリップ全体を読み取り、現在のブロックに含まれていない部分を破棄します。ストリップあたり 34 行、ブロックあたり 500 行なので、関数 blockproc
は各ブロックで 15 回ディスクにアクセスします。イメージの幅は約 6 ブロックです (2956/500 = 5.912)。関数 blockproc
は、あるストリップに含まれているピクセルを含む各ブロックで、同じストリップを何度も読み取ります。イメージの幅は 6 ブロックなので、blockproc
はファイルの各ストリップを 6 回読み取ります。
blockSizeSquare = 500;
tic
im = blockproc('concordorthophoto.tif',[blockSizeSquare blockSizeSquare],@(s) s.data);
toc
Elapsed time is 0.369570 seconds.
ケース 2: 列型のブロック
イメージの高さ全体に及ぶブロックを使用して、イメージを処理します。ストリップ形式の TIFF ファイルは行でまとめられているため、このブロックのレイアウトはディスク上の実際のファイルのレイアウトと正反対です。
ブロックのピクセル数が正方形ブロックのものとほぼ同じになるように、ブロックの幅を選択します。
numCols = ceil(blockSizeSquare.^2 / h)
numCols = 113
イメージの幅は 26 ブロック以上です (2956/numCols
= 26.1593)。各ブロックの各ストリップを読み取らなければなりません。blockproc
はディスクからイメージ全体を 26 回読み取ります。
tic
im = blockproc('concordorthophoto.tif',[h numCols],@(s) s.data);
toc
Elapsed time is 0.176706 seconds.
ケース 3: 行型のブロック
イメージの幅全体に及ぶブロックを使用して、イメージを処理します。このブロック レイアウトは、ディスク上の TIFF ファイルのレイアウトと一致します。
ブロックのピクセル数が正方形ブロックのものとほぼ同じになるように、ブロックの高さを選択します。
numRows = ceil(blockSizeSquare.^2 / w)
numRows = 85
各ブロックの幅はイメージの幅です。このため、blockproc
は各ストリップを一度だけ読み取ります。ブロックのレイアウトが TIFF イメージのストリップと一致している場合に、実行時間が最短となります。
tic
im = blockproc('concordorthophoto.tif',[numRows w],@(s) s.data);
toc
Elapsed time is 0.131992 seconds.