Main Content

为使用半精度数据类型的索贝尔边缘检测生成代码

此示例说明如何从 MATLAB® 函数生成独立的 C++ 库,该库通过使用半精度浮点数执行图像的索贝尔边缘检测。索贝尔边缘算法接受表示为矩阵的图像,并返回强调与其边缘对应的高空间频率区域的图像。此示例还说明如何使用 MEX 函数测试生成的代码。

索贝尔边缘检测算法

在索贝尔边缘检测算法中,对灰度图像执行二维空间梯度运算。此运算强调对应于图像中边缘的高空间频率区域。

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

索贝尔边缘算法通过使用两个正交滤波器核 maskXmaskY 计算输入图像的水平梯度 h 和垂直梯度 v。在滤波运算后,该算法计算梯度幅值,并应用阈值以找到对应于边缘的图像区域。

读取图像并将数据打包为 RGBA 打包的列优先顺序

使用 imread 函数读取图像。imread 用整数表示图像的 RGB 通道,每个像素对应一个通道。整数范围从 0 到 255。简单地将输入转换为半精度类型可能导致卷积过程中发生溢出。要避免此问题,请将图像缩放到 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
//
// File: sobelEdgeDetectionAlg.cpp
//
// MATLAB Coder version            : 24.1
// C/C++ source code generated on  : 20-Apr-2024 05:56:37
//

// 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]
//

另请参阅

| |

相关主题