アプリケーションにおける 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 関数のイメージと一致します。
