Main Content

半精度データ型を使用するソーベル エッジ検出のコードの生成

この例では、半精度浮動小数点数を使用してイメージのソーベル エッジ検出を実行する MATLAB® 関数からスタンドアロンの C++ ライブラリを生成する方法を説明します。ソーベル エッジ アルゴリズムは、行列として表されるイメージを受け取り、そのエッジに対応する高空間周波数領域を強調するイメージを返します。この例では、MEX 関数を使用して生成されたコードをテストする方法も説明します。

ソーベル エッジ検出アルゴリズム

ソーベル エッジ検出アルゴリズムでは、グレースケール イメージに対して 2 次元空間勾配演算が実行されます。この演算では、イメージのエッジに対応する高空間周波数領域が強調されます。

type sobelEdgeDetectionAlg
function edgeImg = sobelEdgeDetectionAlg(img,thresh)  %#codegen
% Entry-point function for half-precision Sobel edge detection example.
% Copyright 2018-2022 The MathWorks, Inc.

kern = half([1 2 1; 0 0 0; -1 -2 -1]);

% Finding horizontal and vertical gradients.
h = conv2(img(:,:,2),kern,'same');
v = conv2(img(:,:,2),kern','same');

% Finding magnitude of the gradients.
e = sqrt(h.*h + v.*v);

% Threshold the edges
edgeImg = uint8((e > thresh) * 240);

end

ソーベル エッジ アルゴリズムでは、2 つの直交フィルター カーネル maskX および maskY を使用して、入力イメージの水平方向の勾配 h と垂直方向の勾配 v を計算します。フィルター処理の後に、アルゴリズムは勾配の大きさを計算し、エッジに対応するイメージの領域を検出するためのしきい値を適用します。

イメージの読み取りと RGBA パックされた列優先の順序へのデータのパック

関数imreadを使用してイメージを読み取ります。imread は、イメージの RGB チャネルを整数 (ピクセルごとに 1 つの整数) で表します。整数の範囲は 0 ~ 255 です。単純に入力を half 型にキャストすると、畳み込み中にオーバーフローが発生する可能性があります。この問題を回避するには、イメージを 0 から 1 の間の値にスケーリングします。

im = imread('peppers.png');
figure();
image(im);
imPacked = half(im)/255;
thresh = half(100)/255;

MEX の生成

codegenコマンドを使用して関数 sobelEdgeDetectionAlg の C++ MEX 関数を生成します。

cfg = coder.config('mex');
cfg.TargetLang = 'C++';
cfg.GenerateReport = true;
codegen -config cfg -args {imPacked,thresh} sobelEdgeDetectionAlg
Code generation successful: To view the report, open('codegen/mex/sobelEdgeDetectionAlg/html/report.mldatx')

生成された MEX の実行と検出されたエッジの表示

C++ コードを生成する前に、MATLAB 環境内で MEX 関数をテストして、その関数が元の MATLAB コードと機能的に等価であることと実行時エラーが発生しないことを確認しなければなりません。既定で、codegen は、現在のフォルダーに sobelEdgeDetectionAlg_mex という名前の MEX 関数を生成します。これにより、MATLAB コードと MEX 関数をテストして結果を比較することができます。

out_disp = sobelEdgeDetectionAlg_mex(imPacked,thresh);
figure();
imagesc(out_disp);

C++ スタティック ライブラリの生成

codegen コマンドを使用して C++ スタティック ライブラリを生成します。既定では、生成されたライブラリはフォルダー codegen/lib/sobelEdgeDetectionAlg/ に配置されます。

cfg = coder.config('lib');
cfg.TargetLang = 'C++';
cfg.GenerateReport = true;
codegen -config cfg -args {imPacked,thresh} sobelEdgeDetectionAlg;
Code generation successful: To view the report, open('codegen/lib/sobelEdgeDetectionAlg/html/report.mldatx')

生成された関数の確認

type codegen/lib/sobelEdgeDetectionAlg/sobelEdgeDetectionAlg.cpp
//
// Prerelease License - for engineering feedback and testing purposes
// only. Not for sale.
// File: sobelEdgeDetectionAlg.cpp
//
// MATLAB Coder version            : 24.1
// C/C++ source code generated on  : 25-Jan-2024 14:58:04
//

// Include Files
#include "sobelEdgeDetectionAlg.h"
#include "conv2MovingWindowSameCM.h"
#include "rtwhalf.h"
#include "sobelEdgeDetectionAlg_data.h"
#include "sobelEdgeDetectionAlg_initialize.h"
#include <cmath>

// Function Definitions
//
// Entry-point function for half-precision Sobel edge detection example.
//  Copyright 2018-2022 The MathWorks, Inc.
//
// Arguments    : const real16_T img[589824]
//                real16_T thresh
//                unsigned char edgeImg[196608]
// Return Type  : void
//
void sobelEdgeDetectionAlg(const real16_T img[589824], real16_T thresh,
                           unsigned char edgeImg[196608])
{
  static const real16_T hv[9]{real16_T(1.0F), real16_T(0.0F), real16_T(-1.0F),
                              real16_T(2.0F), real16_T(0.0F), real16_T(-2.0F),
                              real16_T(1.0F), real16_T(0.0F), real16_T(-1.0F)};
  static const real16_T hv1[9]{
      real16_T(1.0F),  real16_T(2.0F),  real16_T(1.0F),
      real16_T(0.0F),  real16_T(0.0F),  real16_T(0.0F),
      real16_T(-1.0F), real16_T(-2.0F), real16_T(-1.0F)};
  static real16_T h[196608];
  static real16_T v[196608];
  if (!isInitialized_sobelEdgeDetectionAlg) {
    sobelEdgeDetectionAlg_initialize();
  }
  //  Finding horizontal and vertical gradients.
  coder::conv2MovingWindowSameCM(&img[196608], hv, h);
  coder::conv2MovingWindowSameCM(&img[196608], hv1, v);
  //  Finding magnitude of the gradients.
  //  Threshold the edges
  for (int k{0}; k < 196608; k++) {
    real16_T b_h;
    real16_T h1;
    b_h = h[k];
    h1 = v[k];
    b_h = static_cast<real16_T>(
        std::sqrt(static_cast<float>(b_h * b_h + h1 * h1)));
    h[k] = b_h;
    edgeImg[k] = static_cast<unsigned char>((b_h > thresh) * 240U);
  }
}

//
// File trailer for sobelEdgeDetectionAlg.cpp
//
// [EOF]
//

参考

| |

関連するトピック