Main Content

Generate Code for Sobel Edge Detection That Uses Half-Precision Data Type

This example shows how to generate a standalone C++ library from a MATLAB® function that performs Sobel edge detection of images by using half-precision floating point numbers. The Sobel edge algorithm accepts an image that is represented as a matrix and returns an image emphasizing the high spatial frequency regions that correspond to its edges. This example also shows how to test the genenrated code by using a MEX function.

Sobel Edge Detection Algorithm

In the Sobel edge detection algorithm, a 2-D spatial gradient operation is performed on a grayscale image. This operation emphasizes the high spatial frequency regions that correspond to the edges in the image.

type sobelEdgeDetectionAlg
function edgeImg = sobelEdgeDetectionAlg(img,thresh)  %#codegen
%sobelEdgeDetection Example MATLAB function for edge detection.
% Copyright 2018 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

The Sobel edge algorithm computes the horizontal gradient h and the vertical gradient v of the input image by using two orthogonal filter kernels maskX and maskY. After the filtering operation, the algorithm computes the gradient magnitude and applies a threhold to find the regions of the image that correspond to the edges.

Read Images and Pack Data Into RGBA Packed Column Major Order

Use the imread function to read the images. imread represents the RGB channels of an images with integers, one for each pixel. The integers range from 0 to 255. Simply casting inputs to half type might result in overflow during convolutions. To avoid this issue, scale the images to values between 0 and 1.

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

Generate MEX

Generate a C++ MEX function for the sobelEdgeDetectionAlg function by using the codegen command.

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').

Run Generated MEX and Display Detected Edge

Before generating C++ code, you must first test the MEX function inside MATLAB environment to make sure that it is functionally equivalent to the original MATLAB code and that no run-time errors occur. By default, codegen generates a MEX function named sobelEdgeDetectionAlg_mex in the current folder. This allows you to test the MATLAB code and MEX function and compare the results.

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

Generate Static C++ Library

Use the codegen command to produces a C++ static library. By default, the generated library is located in the folder 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').

Inspect the Generated Function

type codegen/lib/sobelEdgeDetectionAlg/sobelEdgeDetectionAlg.cpp
//
// File: sobelEdgeDetectionAlg.cpp
//
// MATLAB Coder version            : 5.2
// C/C++ source code generated on  : 23-Feb-2021 13:32:47
//

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

// Function Definitions
//
// sobelEdgeDetection Example MATLAB function for edge detection.
//  Copyright 2018 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(*(real16_T(*)[196608]) & img[196608], hv, h);
  coder::conv2MovingWindowSameCM(*(real16_T(*)[196608]) & 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]
//

See Also

| |

Related Topics