Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

イメージのエッジ検出

この例では、イメージのエッジ検出を行う単純なソーベル フィルターを実装する 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

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

-config coder.config('lib') オプションを指定して codegen を使用すると、スタンドアロン C ライブラリが生成されます。既定では、ライブラリ用に生成されたコードは codegen/lib/sobel/ フォルダーにあります。

生成された関数の確認

type codegen/lib/sobel/sobel.c
/*
 * File: sobel.c
 *
 * MATLAB Coder version            : 5.1
 * C/C++ source code generated on  : 24-Aug-2020 19:17:27
 */

/* 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 Definitions */
/*
 * 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;
  int k;
  int nx;
  if (!isInitialized_sobel) {
    sobel_initialize();
  }

  emxInit_real_T(&H, 2);
  emxInit_real_T(&V, 2);

  /*  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. */
  conv2AXPYSameCMP(originalImage, H);
  b_conv2AXPYSameCMP(originalImage, V);
  nx = H->size[0] * H->size[1];
  for (k = 0; k < nx; k++) {
    H->data[k] = H->data[k] * H->data[k] + V->data[k] * V->data[k];
  }

  emxFree_real_T(&V);
  nx = H->size[0] * H->size[1];
  for (k = 0; k < nx; 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);
  nx = H->size[0] * H->size[1];
  for (k = 0; k < nx; k++) {
    edgeImage->data[k] = (unsigned char)((H->data[k] > threshold) * 255U);
  }

  emxFree_real_T(&H);
}

/*
 * File trailer for sobel.c
 *
 * [EOF]
 */