# 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 generated 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 % 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 ```

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 threshold 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.6 // C/C++ source code generated on : 03-Mar-2023 04:51:05 // // 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] // ```