このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
イメージのエッジを検出するコードの生成
この例では、イメージのエッジ検出を行う単純なソーベル フィルターを実装する MATLAB® コードからスタンドアロン C ライブラリを生成する方法を示します。また、MATLAB コードがコードの生成に適していることを確認するために、C コードの生成前に MEX 関数を生成してテストする方法も示します。
関数 sobel
について
関数 sobel.m
は、イメージ (double 行列) およびしきい値を取得し、イメージと (しきい値に基づいて) 検出されたエッジを返します。
type sobel
% edgeImage = sobel(originalImage, threshold) % Sobel edge detection. Given a normalized image (with double values) % return an image where the edges are detected w.r.t. threshold value. function edgeImage = sobel(originalImage, threshold) %#codegen assert(all(size(originalImage) <= [1024 1024])); assert(isa(originalImage, 'double')); assert(isa(threshold, 'double')); k = [1 2 1; 0 0 0; -1 -2 -1]; H = conv2(double(originalImage),k, 'same'); V = conv2(double(originalImage),k','same'); E = sqrt(H.*H + V.*V); edgeImage = uint8((E > threshold) * 255);
MEX 関数の生成
codegen
コマンドを使用して MEX 関数を生成します。
codegen sobel
Code generation successful.
C コードを生成する前に、MATLAB で MEX 関数をテストして、その関数が元の MATLAB コードと機能的に等価であることと実行時のエラーが発生しないことを確認しなければなりません。既定で、codegen
は、現在のフォルダーに sobel_mex
という名前の MEX 関数を生成します。これにより、MATLAB コードと MEX 関数をテストして結果を比較することができます。
元のイメージの読み取り
標準の imread
コマンドを使用します。
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;
MEX 関数の実行 (ソーベル フィルター)
正規化されたイメージとしきい値を渡します。
edgeIm = sobel_mex(gray, 0.7);
結果の表示
im3 = repmat(edgeIm, [1 1 3]); image(im3);
スタンドアロン C コードの生成
codegen -config coder.config('lib') sobel
Code generation successful.
-config coder.config('lib')
オプションを指定して codegen
を使用すると、スタンドアロン C ライブラリが生成されます。既定では、ライブラリ用に生成されたコードは codegen/lib/sobel/
フォルダーにあります。
生成された関数の確認
type codegen/lib/sobel/sobel.c
/* * Prerelease License - for engineering feedback and testing purposes * only. Not for sale. * File: sobel.c * * MATLAB Coder version : 23.2 * C/C++ source code generated on : 27-Jul-2023 14:58:09 */ /* Include Files */ #include "sobel.h" #include "conv2AXPYSameCMP.h" #include "sobel_data.h" #include "sobel_emxutil.h" #include "sobel_initialize.h" #include "sobel_types.h" #include <math.h> /* Function Declarations */ static void binary_expand_op(emxArray_real_T *in1, const emxArray_real_T *in2); /* Function Definitions */ /* * Arguments : emxArray_real_T *in1 * const emxArray_real_T *in2 * Return Type : void */ static void binary_expand_op(emxArray_real_T *in1, const emxArray_real_T *in2) { emxArray_real_T *b_in1; const double *in2_data; double *b_in1_data; double *in1_data; int aux_0_1; int aux_1_1; int b_loop_ub; int i; int i1; int loop_ub; int stride_0_0; int stride_0_1; int stride_1_0; int stride_1_1; in2_data = in2->data; in1_data = in1->data; emxInit_real_T(&b_in1, 2); if (in2->size[0] == 1) { loop_ub = in1->size[0]; } else { loop_ub = in2->size[0]; } i = b_in1->size[0] * b_in1->size[1]; b_in1->size[0] = loop_ub; if (in2->size[1] == 1) { b_loop_ub = in1->size[1]; } else { b_loop_ub = in2->size[1]; } b_in1->size[1] = b_loop_ub; emxEnsureCapacity_real_T(b_in1, i); b_in1_data = b_in1->data; stride_0_0 = (in1->size[0] != 1); stride_0_1 = (in1->size[1] != 1); stride_1_0 = (in2->size[0] != 1); stride_1_1 = (in2->size[1] != 1); aux_0_1 = 0; aux_1_1 = 0; for (i = 0; i < b_loop_ub; i++) { for (i1 = 0; i1 < loop_ub; i1++) { double b_in1_tmp; double in1_tmp; in1_tmp = in1_data[i1 * stride_0_0 + in1->size[0] * aux_0_1]; b_in1_tmp = in2_data[i1 * stride_1_0 + in2->size[0] * aux_1_1]; b_in1_data[i1 + b_in1->size[0] * i] = in1_tmp * in1_tmp + b_in1_tmp * b_in1_tmp; } aux_1_1 += stride_1_1; aux_0_1 += stride_0_1; } i = in1->size[0] * in1->size[1]; in1->size[0] = b_in1->size[0]; in1->size[1] = b_in1->size[1]; emxEnsureCapacity_real_T(in1, i); in1_data = in1->data; loop_ub = b_in1->size[1]; for (i = 0; i < loop_ub; i++) { b_loop_ub = b_in1->size[0]; for (i1 = 0; i1 < b_loop_ub; i1++) { in1_data[i1 + in1->size[0] * i] = b_in1_data[i1 + b_in1->size[0] * i]; } } emxFree_real_T(&b_in1); } /* * Arguments : const emxArray_real_T *originalImage * double threshold * emxArray_uint8_T *edgeImage * Return Type : void */ void sobel(const emxArray_real_T *originalImage, double threshold, emxArray_uint8_T *edgeImage) { emxArray_real_T *H; emxArray_real_T *V; double *H_data; double *V_data; int k; int loop_ub; unsigned char *edgeImage_data; if (!isInitialized_sobel) { sobel_initialize(); } /* edgeImage = sobel(originalImage, threshold) */ /* Sobel edge detection. Given a normalized image (with double values) */ /* return an image where the edges are detected w.r.t. threshold value. */ emxInit_real_T(&H, 2); conv2AXPYSameCMP(originalImage, H); H_data = H->data; emxInit_real_T(&V, 2); b_conv2AXPYSameCMP(originalImage, V); V_data = V->data; if ((H->size[0] == V->size[0]) && (H->size[1] == V->size[1])) { loop_ub = H->size[0] * H->size[1]; for (k = 0; k < loop_ub; k++) { H_data[k] = H_data[k] * H_data[k] + V_data[k] * V_data[k]; } } else { binary_expand_op(H, V); H_data = H->data; } emxFree_real_T(&V); loop_ub = H->size[0] * H->size[1]; for (k = 0; k < loop_ub; k++) { H_data[k] = sqrt(H_data[k]); } k = edgeImage->size[0] * edgeImage->size[1]; edgeImage->size[0] = H->size[0]; edgeImage->size[1] = H->size[1]; emxEnsureCapacity_uint8_T(edgeImage, k); edgeImage_data = edgeImage->data; for (k = 0; k < loop_ub; k++) { edgeImage_data[k] = (unsigned char)((unsigned int)(H_data[k] > threshold) * 255U); } emxFree_real_T(&H); } /* * File trailer for sobel.c * * [EOF] */