このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
アプリケーションにおける C の main の例の使用
この例では、イメージのエッジ検出を行う単純なソーベル フィルターを実装する MATLAB® コードから C 実行可能ファイルをビルドする方法を示します。実行可能ファイルはディスクからイメージを読み取り、ソーベル フィルター アルゴリズムを適用して、変更されたイメージを保存します。
この例では、実行可能ファイルをビルドする際に使用する main 関数の例を生成して変更する方法を示します。
必要条件
この例を実行するには、次の製品をインストールします。
MATLAB
MATLAB Coder™
C コンパイラ (ほとんどのプラットフォーム用に、既定の C コンパイラが MATLAB に付属しています)。サポートされているコンパイラのリストは、サポートされるコンパイラを参照してください。
mex -setup
を使用して既定のコンパイラを変更できます。既定のコンパイラの変更を参照してください。
チュートリアル ファイル: ソーベル フィルター
この例を開いて、このチュートリアルのファイル sobel.m
と hello.jpg
を取得します。
チュートリアル ファイルの説明
この例では次のファイルを使用します。
ファイル名 | ファイルの種類 | 説明 |
---|---|---|
sobel.m | 関数のコード | MATLAB によるソーベル フィルター アルゴリズムの実装。sobel.m はイメージ (double 行列) およびしきい値を入力として取得します。アルゴリズムはイメージのエッジを (しきい値に基づいて) 検出します。sobel.m はエッジを表示する変更されたイメージを返します。 |
hello.jpg | イメージ ファイル | ソーベル フィルターによって変更されるイメージ。 |
イメージに対するソーベル フィルターの実行
元のイメージを MATLAB 行列に読み取り、表示します。
im = imread('hello.jpg');
ソーベル フィルターの結果との比較対象としてイメージを表示します。
image(im);
ソーベル フィルター アルゴリズムはグレースケール イメージで動作します。正規化された値 (0.0 が黒、1.0 が白) を使ってカラー イメージを等価のグレースケール イメージに変換します。
gray = (0.2989 * double(im(:,:,1)) + 0.5870 * double(im(:,:,2)) + 0.1140 * double(im(:,:,3)))/255;
ソーベル フィルターに対して MATLAB 関数を実行するには、グレースケール イメージ行列
gray
としきい値を関数sobel
に渡します。この例では 0.7 をしきい値に使用します。edgeIm = sobel(gray, 0.7);
変更したイメージを表示するには、行列
edgeIm
の形式を関数repmat
で変更し、image
コマンドに渡せるようにします。im3 = repmat(edgeIm, [1 1 3]); image(im3);
MEX 関数の生成とテスト
生成されたコードが元の MATLAB コードと機能的に等価であり、ランタイム エラーが発生しないことをテストするには、MEX 関数を生成します。
codegen -report sobel
codegen
は現在の作業フォルダーにsobel_mex
という名前の MEX 関数を生成します。ソーベル フィルターに対して MEX 関数を実行するには、グレースケール イメージ行列
gray
としきい値を関数sobel_mex
に渡します。この例では 0.7 をしきい値に使用します。edgeImMex = sobel_mex(gray, 0.7);
変更したイメージを表示するには、行列
edgeImMex
の形式を関数repmat
で変更し、image
コマンドに渡せるようにします。im3Mex = repmat(edgeImMex, [1 1 3]); image(im3Mex);
このイメージは MATLAB 関数を使用して作成されたイメージと同じです。
sobel.m 用の main 関数の例の生成
アプリケーション用にカスタム main 関数を作成することはできますが、main 関数の例は生成されたコードを組み込む際に役立つテンプレートを提供します。
ソーベル フィルター用に main 関数の例を生成するには、次の手順に従います。
C スタティック ライブラリ用に構成オブジェクトを作成します。
cfg = coder.config('lib');
C/C++ ソース コード、スタティック ライブラリ、ダイナミック ライブラリおよび実行可能ファイルの構成オブジェクトに対して、設定
GenerateExampleMain
は main 関数の例の生成を制御します。この設定は main 関数の例を生成してもコンパイルはしない'GenerateCodeOnly'
に、既定で設定されます。この例では、GenerateExampleMain
設定の値は変更しないでください。構成オブジェクトを使用して C スタティック ライブラリを生成します。
codegen -report -config cfg sobel
スタティック ライブラリに生成されたファイルはフォルダー codegen/lib/sobel
に格納されています。メイン ファイルの例は、サブフォルダー codegen/lib/sobel/examples
に格納されています。
メイン ファイルの例のコピー
ファイル main.c
と main.h
を examples
サブフォルダーで変更しないでください。変更すると、コードの再生成時に MATLAB Coder でメイン ファイルの例が再生成されません。生成されたファイルに対する変更が検出されたことを警告します。
ファイル main.c
と main.h
をフォルダー codegen/lib/sobel/examples
から別の場所へコピーします。この例では、ファイルを現在の作業フォルダーへコピーします。新しい場所でファイルを変更します。
生成された main 関数の例の変更
main 関数の例は動的に割り当てられたデータなどのデータを宣言して、ゼロ値に初期化します。これは、ゼロ値に設定された引数でエントリポイント関数を呼び出しますが、エントリポイント関数から返される値は使用しません。
C の main 関数はアプリケーションの要件を満たしていなければなりません。この例では、ソーベル フィルター アプリケーションの要件を満たすように main 関数の例を変更しています。
この例では、ソーベル フィルター アプリケーションが次を実行するように、ファイル main.c
を変更しています。
バイナリ ファイルからグレースケール イメージを読み込む。
ソーベル フィルター アルゴリズムを適用する。
変更されたイメージをバイナリ ファイルに保存する。
main 関数の変更
次を実行するように main
関数を変更します。
グレースケール イメージ データとしきい値を含むファイルを入力引数として受け入れます。
グレースケール イメージ データ ストリームのアドレスとしきい値を入力引数として指定して関数
main_sobel
を呼び出します。
main
関数で次を実行します。
宣言
(void)argc
と(void)argv
を削除します。変数
filename
を宣言し、グレースケール イメージ データを含むバイナリ ファイルの名前を保持します。const char *filename;
変数
threshold
を宣言し、しきい値を保持します。double threshold;
変数
fd
を宣言し、アプリケーションがfilename
から読み取るグレースケール イメージ データのアドレスを保持します。FILE *fd;
3 つの引数をチェックする
if
ステートメントを追加します。if (argc != 3) { printf("Expected 2 arguments: filename and threshold\n"); exit(-1); }
グレースケール イメージ データを含むファイルの入力引数
argv[1]
をfilename
に代入します。filename = argv[1];
しきい値の入力引数
argv[2]
をthreshold
に代入し、入力を文字列から double の数値に変換します。threshold = atof(argv[2]);
名前が
filename
に指定されているグレースケール イメージ データを含んだファイルを開きます。データ ストリームのアドレスをfd
に代入します。fd = fopen(filename, "rb");
実行可能ファイルが
filename
を開くことを検証するには、fd
の値がNULL
の場合にプログラムを終了するif
ステートメントを記述します。if (fd == NULL) { exit(-1); }
入力引数
fd
とthreshold
を指定してmain_sobel
を呼び出し、main_sobel
の関数呼び出しを置き換えます。main_sobel(fd, threshold);
sobel_terminate
を呼び出した後、グレースケール イメージ ファイルを閉じます。fclose(fd);
初期化関数 argInit_d1024xd1024_real_T の変更
メイン ファイルの例で、関数 argInit_d1024xd1024_real_T
はソーベル フィルターに渡すイメージに対して動的に割り当てられた可変サイズの配列 (emxArray) を作成します。この関数は emxArray を既定サイズに初期化し、emxArray の要素を 0 にします。これは初期化された emxArray を返します。
ソーベル フィルター アプリケーションの場合、バイナリ ファイルからグレースケール イメージ データを emxArray に読み取るように関数を変更します。
関数 argInit_d1024xd1024_real_T
で次を実行します。
入力引数
void
を引数FILE *fd
と置き換えます。この変数は関数が読み取るグレースケール イメージ データを指します。static emxArray_real_T *argInit_d1024xd1024_real_T(FILE *fd)
グレースケール イメージ行列
gray
の次元と一致するように変数idx0
およびidx1
の値を変更します。これらの変数はargInit_d1024xd1024_real_T
で作成される emxArray の次元のサイズ値を保持します。int idx0 = 484; int idx1 = 648;
MATLAB は列優先の形式でデータを格納し、C は行優先の形式で行列データを格納します。次元を適宜宣言します。
関数
emxCreate_real_T
の値をイメージ サイズに変更します。result = emxCreate_real_T(484, 648);
グレースケール イメージ データから読み取る値を保持する変数
element
を定義します。double element;
for
ループの構成を変更し、fread
コマンドを内部for
ループに追加してデータ点を正規化イメージからelement
に読み取ります。fread(&element, 1, sizeof(element), fd);
for
ループ内部でelement
を emxArray データの値セットとして代入します。result->data[idx0 + result->size[0] * idx1] = element;
関数 saveImage の作成
MATLAB 関数 sobel.m
は MATLAB 配列とインターフェイスを取りますが、ソーベル フィルター アプリケーションはバイナリ ファイルとインターフェイスを取ります。
ソーベル フィルター アルゴリズムで変更されたイメージをバイナリ ファイルに保存するには、関数 saveImage
を作成します。関数 saveImage
は emxArray のデータをバイナリ ファイルに書き込みます。これは関数 argInit_d1024xd1024_real_T
で使用する構成と同様の構成を使用します。
main.c
ファイルで次のことを行います。
emxArray
edgeImage
のアドレスを入力として受け取り、出力タイプ void をもつ関数saveImage
を定義します。static void saveImage(emxArray_uint8_T *edgeImage) { }
変数
idx0
と変数idx1
を関数argInit_d1024xd1024_real_T
で定義する場合と同じように定義します。int idx; int idx1;
emxArray から読み取るデータを格納するように変数
element
を定義します。uint8_T element;
変更されたイメージの書き込み用にバイナリ ファイル
edge.bin
を開きます。edge.bin
のアドレスをFILE *fd
に代入します。FILE *fd = fopen("edge.bin", "wb");
実行可能ファイルが
edge.bin
を開くことを検証するには、fd
の値がNULL
の場合にプログラムを終了するif
ステートメントを記述します。if (fd == NULL) { exit(-1); }
入れ子にされた
for
ループの構成を関数argInit_d1024xd1024_real_T
の構成と同じように書き込みます。for (idx0 = 0; idx0 < edgeImage->size[0U]; idx0++) { for (idx1 = 0; idx1 < edgeImage->size[1U]; idx1++) { } }
内部
for
ループで、変更されたイメージ データの値をelement
に代入します。element = edgeImage->data[idx0 + edgeImage->size[0] * idx1];
element
の代入後、element
の値をファイルedge.bin
に書き込みます。fwrite(&element, 1, sizeof(element), fd);
for
ループの構成後、fd
を閉じます。fclose(fd);
関数 main_sobel の変更
この main 関数の例では、関数 main_sobel
はグレースケールのデータと変更されたイメージに emxArrays を作成します。これは、グレースケール イメージの emxArray を初期化する関数 argInit_d1024xd1024_real_T
を呼び出します。main_sobel
は、emxArrays と、初期化関数 argInit_real_T
が関数 sobel
に返すしきい値 0 の両方を渡します。関数 main_sobel
が終了すると、関数 sobel
の結果を破棄します。
ソーベル フィルター アプリケーションの場合、関数 main_sobel
を次に変更します。
グレースケール イメージ データのアドレスとしきい値を入力として受け取ります。
argInit_d1024xd1024_real_T
を使用してアドレスからデータを読み取ります。しきい値
threshold
でデータをソーベル フィルター アルゴリズムに渡します。saveImage
を使用して結果を保存します。
関数 main_sobel
で次を実行します。
引数
FILE *fd
とdouble threshold
をもつ関数と入力引数を置き換えます。static void main_sobel(FILE *fd, double threshold)
入力引数
fd
をargInit_d1024xd1024_real_T
の関数呼び出しに渡します。originalImage = argInit_d1024xd1024_real_T(fd);
関数呼び出し内のしきい値の入力を
threshold
をもつsobel
に置き換えます。sobel(originalImage, threshold, edgeImage);
関数
sobel
を呼び出した後、入力edgeImage
をもつ関数saveImage
を呼び出します。saveImage(edgeImage);
関数宣言の変更
関数宣言に加えた変更と一致させるには、関数宣言に次の変更を加えます。
関数
*argInit_d1024xd1024_real_T
の入力をFILE *fd
に変更します。static emxArray_real_T *argInit_d1024xd1024_real_T(FILE *fd);
関数
main_sobel
の入力をFILE *fd
とdouble threshold
に変更します。static void main_sobel(FILE *fd, double threshold);
関数
saveImage
を追加します。static void saveImage(emxArray_uint8_T *edgeImage);
インクルード ファイルの変更
main.c
で使用する入出力関数の場合、ヘッダー ファイル stdio.h
をインクルード ファイル リストに追加します。
#include <stdio.h>
変更されたファイル main.c
の内容
ソーベル フィルター アプリケーションの生成
作業フォルダーに移動します (現在作業フォルダー以外にいる場合)。
C スタンドアロンの実行可能ファイルに構成オブジェクトを作成します。
cfg = coder.config('exe');
構成オブジェクトと変更された main 関数を使用して、ソーベル フィルターに C スタンドアロンの実行可能ファイルを生成します。
codegen -report -config cfg sobel main.c main.h
既定では、MATLAB を Windows® プラットフォームで実行している場合、実行可能ファイル sobel.exe
は現在の作業フォルダーに生成されます。MATLAB を Windows 以外のプラットフォームで実行している場合、ファイルの拡張子はそのプラットフォームに対応する拡張子になります。既定の設定では、実行可能ファイルの生成されたコードはフォルダー codegen/exe/sobel
にあります。
ソーベル フィルター アプリケーションの実行
MATLAB 行列
gray
が現在 MATLAB ワークスペースにない場合は、作成します。im = imread('hello.jpg');
gray = (0.2989 * double(im(:,:,1)) + 0.5870 * double(im(:,:,2)) + 0.1140 * double(im(:,:,3)))/255;
行列
gray
をfopen
とfwrite
コマンドを使用してバイナリ ファイルに書き込みます。アプリケーションはこのバイナリ ファイルを読み取ります。fid = fopen('gray.bin', 'w'); fwrite(fid, gray, 'double'); fclose(fid);
実行可能ファイルを実行して、ファイル
gray.bin
およびしきい値 0.7 を渡します。この例を Windows プラットフォームの MATLAB で実行するには、次を行います。
system('sobel.exe gray.bin 0.7');
実行可能ファイルはファイル
edge.bin
を生成します。
結果として得たイメージの表示
fopen
とfread
コマンドを使用して、ファイルedge.bin
を MATLAB 行列edgeImExe
に読み取ります。fd = fopen('edge.bin', 'r'); edgeImExe = fread(fd, size(gray), 'uint8'); fclose(fd);
行列
edgeImExe
を関数repmat
に渡し、イメージを表示します。im3Exe = repmat(edgeImExe, [1 1 3]); image(im3Exe);
イメージは MATLAB と MEX 関数のイメージと一致します。