このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
大きなイメージのブロック処理
この例では、TIFF イメージをブロックに分割して、イメージのエッジ検出を行う方法を説明します。大きなイメージを処理する場合、通常のイメージ処理手法が正常に機能しない場合があります。イメージがメモリに読み込むには大きすぎるか、メモリに読み込めるが大きすぎて処理できないことが原因と考えられます。
これらの問題を回避するには、イメージを複数の領域に分割し、各領域を別々に読み取り、処理し、最後に結果をディスクに書き込み、全体のイメージを再構築します。関数 blockproc
はこの処理に役立ちます。関数 blockproc
を使用して、イメージ、ブロック サイズおよび関数ハンドルを指定します。blockproc
は、入力イメージを指定されたサイズのブロックに分け、関数ハンドルを使用してブロックを 1 つずつ処理し、結果を集めて出力イメージを作成します。blockproc
は出力をメモリまたはディスク上の新しいファイルに返します。
最初に、ブロック処理を使用しないでエッジ検出を実行した場合の結果を検討します。この例では小さなイメージ cameraman.tif
を使用して概念を説明しますが、大きなイメージではしばしばブロック処理が役立ちます。
file_name = "cameraman.tif"; I = imread(file_name); normal_edges = edge(I,"canny"); imshow(I) title("Original Image")
imshow(normal_edges)
title("Conventional Edge Detection")
次にブロック処理を使用して同じ作業を行います。関数 blockproc
には TIFF イメージのサポートが組み込まれているため、imread
を使用してファイルをすべてメモリに読み取る必要はありません。代わりに、string ファイル名を入力に使用して関数を呼び出します。blockproc
は 1 ブロック単位で読み取るので、非常に大きなイメージにはこのワークフローが理想的です。
大きなイメージを処理する場合、名前と値の引数 "Destination"
を使用して、blockproc
が出力イメージを書き込むファイルを指定することがよくあります。ただし、この例では結果をメモリ内の変数に返します。
この例では [50 50]
のブロック サイズを使用します。通常、大きなブロック サイズを選択すると blockproc
のパフォーマンスが向上します。これは、ディスクへのアクセスが大幅なパフォーマンス コストにつながるファイルツーファイルのワークフローに特に当てはまります。適切なブロック サイズは利用可能なマシン リソースによって異なりますが、次元あたり数千ピクセルの範囲にする必要があります。
% You can use an anonymous function to define the function handle. The % function is passed a structure as input, a "block struct", with several % fields containing the block data as well as other relevant information. % The function should return the processed block data. edgeFun = @(block_struct) edge(block_struct.data,"canny"); block_size = [50 50]; block_edges = blockproc(file_name,block_size,edgeFun); imshow(block_edges) title("Block Processing - Simplest Syntax")
ブロック処理にはかなり不自然な影響があることに注意してください。ピクセルがエッジ ピクセルかどうかを判定するには、隣接するピクセルからの情報が必要です。これは、各ブロックは周囲のピクセルと完全に切り離して処理することはできないことを意味します。この問題を修復するには、blockproc
の名前と値の引数 "BorderSize"
を使用して、各ブロックの周りの横方向および縦方向の境界を指定します。必要な "BorderSize"
は実行中のタスクに応じて異なります。
border_size = [10 10]; block_edges = blockproc(file_name,block_size,edgeFun,"BorderSize",border_size); imshow(block_edges) title("Block Processing - Block Borders")
ブロックは、現在、両面に 10 ピクセルのイメージ データを追加して処理されています。これは良さそうに見えますが、結果は元のメモリ内結果とは大幅に異なります。この理由は、キャニー エッジ検出法で使用するしきい値が、完全なイメージ ヒストグラムに基づいて計算されいるためです。関数 blockproc
は各ブロックの関数 edge
を呼び出すため、キャニー アルゴリズムが不完全なヒストグラムで作業することになり、イメージ全体で異なるしきい値が使用されます。
イメージをブロック処理するときには、このようなタイプのアルゴリズム制約を理解することが重要です。一部の関数は、すべての構文を直接ブロック処理に変換するわけではありません。この場合、関数 edge
を使用して、固定しきい値を計算する代わりに入力引数として渡すことができます。関数ハンドルを修正して edge
の 3 引数構文を使用すると、関数のいずれかの "グローバルな" 制約が削除されます。試行錯誤により、しきい値が 0.09
のときに良い結果になることがわかっています。
thresh = 0.09; edgeFun = @(block_struct) edge(block_struct.data,"canny",thresh); block_edges = blockproc(file_name,block_size,edgeFun,"BorderSize",border_size); imshow(block_edges) title("Block Processing - Borders & Fixed Threshold")
結果は元のメモリ内の結果とほぼ一致しています。境界沿いに不自然な影響が見られます。これらは、キャニー エッジ検出法で使われた別のパディング方法が原因です。現在、blockproc
はイメージ境界でゼロ パディングのみをサポートしています。