Main Content

サポートされない形式のイメージ ファイルに対するブロック処理の実行

関数 blockproc は、TIFF または JPEG2000 ファイルを読み取ったり、TIFF ファイルに書き込んだりするだけでなく、他の形式でも読み取りや書き込みができます。別のファイル形式でイメージ データを操作するには、ImageAdapter クラスから継承するクラスを作成しなければなりません。ImageAdapter クラスは Image Processing Toolbox™ ソフトウェアの一部である抽象クラスです。これは、blockproc がディスク上のイメージのファイル I/O に使用するメソッドのシグネチャを定義します。イメージ アダプター クラスのインスタンスをファイルに関連付け、blockproc への引数として使用してファイルベースのブロック処理を行うことができます。

このセクションでは、サンプル クラス (LanAdapter クラス) について説明して、イメージ アダプター クラスの書き込みプロセスを示します。LanAdapter クラスはツールボックスの一部です。この単純な読み取り専用のクラスを使用して、任意の大きさの uint8 LAN ファイルを blockproc で処理します。

LAN ファイル形式の詳細

LanAdapter クラスの動作について理解するには、まず LAN ファイル形式について知らなければなりません。Landsat Thematic Mapper 撮影画像が Erdas LAN ファイル形式で格納されています。Erdas LAN ファイルには 128 バイトのヘッダーが含まれ、その後にデータの 1 つ以上のスペクトル バンド、ライン挟み込みバンド並び (BIL) が帯域番号の昇順で含まれています。データはリトルエンディアンの順番で格納されています。ヘッダーには、サイズ、データ型、ファイル内の撮影画像の帯域数などのファイルに関する複数の重要情報が含まれています。LAN ファイル形式の仕様は、次の表に示すように、ファイル ヘッダーの最初の 24 バイトを定義します。

ファイル ヘッダーの内容

バイトデータ型内容
1–6ファイル形式のバージョンを識別する 6 バイトの文字配列'HEADER' または 'HEAD74' (7.4 以前のファイルは 'HEADER' を表示)
7–816 ビット整数ファイルのパック タイプ (ビット深度を示す)
9–1016 ビット整数データの帯域数
11–166 バイト未使用
17–2032 ビット整数データの列数
21–2432 ビット整数データの行数

残りの 104 バイトにはファイルの他のさまざまなプロパティが含まれていますが、この例では使用しません。

ヘッダーの解析

通常、LAN ファイルを操作するときは、最初にヘッダーを解析してファイルの詳細を調べます。次のコードは、rio.lan ファイルのヘッダーを解析する方法を示しています。

  1. ファイルを開きます。

    file_name = 'rio.lan';
    fid = fopen(file_name,'r');
  2. ヘッダーの最初の 6 バイトを読み取ります。

    headword = fread(fid,6,'uint8=>char')';
    fprintf('Version ID: %s\n',headword);
  3. パック タイプを読み取ります。

    pack_type = fread(fid,1,'uint16',0,'ieee-le');
    fprintf('Pack Type: %d\n',pack_type);
  4. スペクトル バンド数を読み取ります。

    num_bands = fread(fid,1,'uint16',0,'ieee-le');
    fprintf('Number of Bands: %d\n',num_bands);
  5. イメージの幅と高さを読み取ります。

    unused_bytes = fread(fid,6,'uint8',0,'ieee-le');
    width = fread(fid,1,'uint32',0,'ieee-le');
    height = fread(fid,1,'uint32',0,'ieee-le');
    fprintf('Image Size (w x h): %d x %d\n',width,height);
  6. ファイルを閉じます。

    fclose(fid);

以下のような出力が表示されます。

Version ID: HEAD74
Pack Type: 0
Number of Bands: 7
Image Size (w x h): 512 x 512

rio.lan ファイルは 512 行 512 列のサイズで、7 バンド イメージです。パック タイプ 0 は、各サンプルが 8 ビットの符号なし整数 (uint8 データ型) であることを示しています。

ファイルの読み取り

一般的なインメモリ ワークフローの場合、関数 multibandread を使用してこの LAN ファイルを読み取ります。LAN 形式にはそれぞれバンド 3、2、1 の可視スペクトルの RGB データが格納されています。トゥルーカラー イメージを作成して、処理を進めることができます。

truecolor = multibandread('rio.lan', [512, 512, 7],...
   'uint8=>uint8', 128,'bil', 'ieee-le', {'Band','Direct',[3 2 1]});

ただし、非常に大きな LAN ファイルの場合、システム機能によっては multibandread を使用してメモリ内のイメージ全体を読み取って処理することが現実的でない場合があります。メモリ制限を回避するには、関数 blockproc を使用します。blockproc を使用すると、ファイルベースのワークフローでイメージを処理できます。一度に 1 ブロックを読み取って処理し、結果を書き込むことができます。

関数 blockproc は特定のファイル形式の読み取りと書き込みのみをサポートしていますが、ImageAdapter クラスを介して拡張できます。特定のファイル形式でイメージ アダプター クラスを書き込むには、次の操作が可能でなければなりません。

  • ディスク上のファイル サイズをクエリする

  • ファイルからデータの四角形ブロックを読み取る

これら 2 つの条件を満たす場合、LAN ファイルでイメージ アダプター クラスを書き込むことができます。イメージ ヘッダーを解析してファイル サイズをクエリし、multibandread への呼び出しを変更して、データの特定のブロックを読み取ることができます。これらの 2 つの目的関数のコードをイメージ アダプター クラス構造体にカプセル化してから、関数 blockproc を使用して大きな LAN ファイルを直接操作できます。LanAdapter クラスは LAN ファイルのイメージ アダプター クラスであり、Image Processing Toolbox ソフトウェアの一部です。

LanAdapter クラスの検証

この節では、LanAdapter クラスのコンストラクター、プロパティ、およびメソッドについて説明します。LanAdapter クラスについて学習すると、独自のイメージ アダプター クラスの記述の準備に役立ちます。オブジェクト指向プログラミングを初めて使用する場合、クラス記述の一般的な情報については、クラスの開発 — 一般的なワークフローを参照してください。

LanAdapter.m を開いて、LanAdapter クラスの実装について確認しましょう。

Classdef

LanAdapter クラスはキーワード classdef で開始されます。classdef セクションはクラスの名前を定義し、LanAdapterImageAdapter スーパークラスから継承されることを示します。ImageAdapter から継承すると、新しいクラスでは次のことができます。

  • blockproc とのやり取り

  • 共通の ImageAdapter プロパティの定義

  • blockproc が LAN ファイルの読み取りおよび書き込みに使用するインターフェイスの定義

プロパティ

classdef セクションの後の LanAdapter クラスには、クラス プロパティの 2 つのブロックが含まれています。最初のブロックには、公開表示できるが公開変更できないプロパティが含まれています。2 番目のブロックには完全にパブリックなプロパティが含まれています。LanAdapter クラスは、ファイル ヘッダーの一部の情報をクラス プロパティとして格納します。ImageAdapter から継承するが別のファイル形式をサポートする他のクラスには、別のプロパティがある場合があります。

classdef LanAdapter < ImageAdapter
   properties(GetAccess = public, SetAccess = private)
      Filename
      NumBands
   end

   properties(Access = public)
      SelectedBands
   end

LanAdapter.m に定義されたプロパティに加え、クラスは ImageAdapter スーパークラスから ImageSize プロパティを継承します。新しいクラスはコンストラクター内に ImageSize プロパティを設定します。

メソッド: クラス コンストラクター

クラス コンストラクターは LanAdapter オブジェクトを初期化します。LanAdapter コンストラクターは LAN ファイルのヘッダー情報を解析し、クラス プロパティを設定します。methods ブロック内のコンストラクター、つまりクラス メソッドを実装します。

コンストラクターには、LAN ファイルのヘッダーの解析に使用したものと同じコードの大部分が含まれています。LanAdapter クラスは uint8 データ型のファイルしかサポートしないので、コンストラクターは LAN ファイルのパック タイプとヘッドワードを検証します。クラス プロパティにはその他の情報が格納されます。ピクセル データの読み取りを行うメソッドではこれらのプロパティを使用します。SelectedBands プロパティを使用すると、すべてのバンドを読み取るという既定の設定で、バンドのサブセットを読み取ることができます。

   methods

      function obj = LanAdapter(fname)
         % LanAdapter constructor for LanAdapter class.
         % When creating a new LanAdapter object, read the file
         % header to validate the file as well as save some image
         % properties for later use.
            
         % Open the file.
         obj.Filename = fname;
         fid = fopen(fname,'r');

         % Verify that the file begins with the headword 'HEADER' or
         % 'HEAD74', as per the Erdas LAN file specification.
         headword = fread(fid,6,'uint8=>char');
         if ~(strcmp(headword','HEADER') || strcmp(headword',...
               'HEAD74'))
            error('Invalid LAN file header.');
         end

         % Read the data type from the header.
         pack_type = fread(fid,1,'uint16',0,'ieee-le');
         if ~isequal(pack_type,0)
            error(['Unsupported pack type. The LanAdapter example ' ...
               'only supports reading uint8 data.']);
         end

         % Provide band information.
         obj.NumBands = fread(fid,1,'uint16',0,'ieee-le');
         % By default, return all bands of data
         obj.SelectedBands = 1:obj.NumBands;

         % Specify image width and height.
         unused_field = fread(fid,6,'uint8',0,'ieee-le');
         width = fread(fid,1,'uint32',0,'ieee-le');
         height = fread(fid,1,'uint32',0,'ieee-le');
         obj.ImageSize = [height width];

         % Close the file handle
         fclose(fid);

   end % LanAdapter 

メソッド: 必須

アダプター クラスには、抽象スーパークラス ImageAdapter 内に定義された 2 つの必須メソッドがあります。すべてのイメージ アダプター クラスはこれらのメソッドを実装しなければなりません。関数 blockproc は最初のメソッド readRegion を使用してディスク上のファイルからデータのブロックを読み取ります。第 2 のメソッド close はイメージ アダプター オブジェクトで必要なクリーンアップを実行します。

   function data = readRegion(obj, region_start, region_size)
      % readRegion reads a rectangular block of data from the file.

      % Prepare various arguments to MULTIBANDREAD.
      header_size = 128;
      rows = region_start(1):(region_start(1) + region_size(1) - 1);
      cols = region_start(2):(region_start(2) + region_size(2) - 1);
 
      % Call MULTIBANDREAD to get data.
      full_size = [obj.ImageSize obj.NumBands];
      data = multibandread(obj.Filename, full_size,...
     'uint8=>uint8', header_size, 'bil', 'ieee-le',...
         {'Row',   'Direct', rows},...
         {'Column','Direct', cols},...
         {'Band',  'Direct', obj.SelectedBands});
 
   end % readRegion

readRegion には 2 つの入力引数 region_start および region_size があります。region_start 引数は [row col] という形式の 2 つの要素のベクトルで、データのリクエスト ブロック内の最初のピクセルを定義します。region_size 引数は [num_rows num_cols] という形式の 2 つの要素のベクトルで、データのリクエストされたブロックのサイズを定義します。readRegion メソッドはこれらの入力引数を使用して、イメージからデータのリクエストされたブロックを読み取って、返します。

readRegion メソッドは、特定のファイルの読み取りにどのツールを使用できるかによって、さまざまなファイル形式で異なる実装が行われます。LanAdapter クラスの readRegion メソッドでは、入力引数を使用して multibandread のカスタム入力を準備します。LAN ファイルの場合、multibandread ではイメージの特定のサブセクションを読み取る便利な方法を使用できます。

この他に必要とされるメソッドは close です。LanAdapter クラスの close メソッドは次のように表示されます。

      function close(obj)
      % Close the LanAdapter object. This method is a part
      % of the ImageAdapter interface and is required.
      % Since the readRegion method is "atomic", there are
      % no open file handles to close, so this method is empty.

      end
        
   end % public methods
    
end % LanAdapter

コメントが示すように、LanAdapterclose メソッドには実行するものがなく、close は空です。関数 multibandread は開いているファイル ハンドルの保守が必要ないため、close メソッドにはクリーンアップするハンドルがありません。他のファイル形式のイメージ アダプター クラスには、ファイル ハンドルの終了や他のクラスのクリーンアップの役割の実行などの、さらに多くの close メソッドがあります。

メソッド (オプション)

前述のように、LanAdapter クラスは LAN ファイルを読み取れますが書き込めません。LAN 形式のファイル、または blockproc でサポートされていない形式のファイルに出力を書き込むには、writeRegion のオプションのメソッドを実装します。次に、クラスを blockproc'Destination' パラメーターとして指定して、選択した形式のファイルに出力を書き込むことができます。

writeRegion メソッドのシグネチャは以下のとおりです。

function [] = writeRegion(obj, region_start, region_data)

最初の引数 region_start は、writeRegion メソッドが書き込むブロックの最初のピクセルを示します。2 番目の引数 region_data には、メソッドがファイルに書き込む新しいデータが含まれています。

writeRegion メソッドを実装するクラスは LanAdapter よりもさらに複雑である場合があります。書き込み可能なイメージ アダプター オブジェクトを作成するとき、クラスはクラス コンストラクターに新しいファイルをさらに作成しなければならない場合がよくあります。このファイル作成ではコンストラクター内にさらに複雑な構文が必要です。ここでは、作成する新しいファイルのサイズとデータ型を指定しなければならない場合があります。また、新しいファイルを作成するコンストラクターでも、オペレーティング システムのファイル アクセス許可や難しいファイル作成コードなどの他の問題が発生することがあります。

blockproc での LanAdapter クラスの使用

これで、LanAdapter クラスの動作を理解できました。このクラスを使用して LAN ファイルの可視帯域を強化できます。関数 blockprocLanAdapter クラスをどのように処理するかについては、大きなイメージの統計値の計算の例を参照してください。

参考

| |

関連するトピック