Main Content

本页的翻译已过时。点击此处可查看最新英文版本。

生成代码以检测图像边缘

此示例说明如何从 MATLAB® 代码生成独立 C 库,该库实现一个简单的 Sobel 滤波器,该滤波器对图像执行边缘检测。示例还说明如何在生成 C 代码之前在 MATLAB 中生成和测试 MEX 函数,以验证该 MATLAB 代码适合进行代码生成。

关于 sobel 函数

sobel.m 函数接受一个图像(表示为双精度矩阵)和一个阈值,并返回一个检测到边缘的图像(基于阈值)。

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
Code generation successful.

在生成 C 代码之前,应首先在 MATLAB 中测试 MEX 函数,以确保它在功能上等同于原始 MATLAB 代码,并且不会出现任何运行时错误。默认情况下,codegen 在当前文件夹中生成名为 sobel_mex 的 MEX 函数。这允许您测试 MATLAB 代码和 MEX 函数,并将结果进行比较。

读取原始图像

使用标准 imread 命令。

im = imread('hello.jpg');
image(im);

Figure contains an axes. The axes contains an object of type image.

将图像转换为灰度版本

使用归一化值(0.0 代表黑色、1.0 代表白色),将彩色图像(如上所示)转换为等效的灰度图像。

gray = (0.2989 * double(im(:,:,1)) + 0.5870 * double(im(:,:,2)) + 0.1140 * double(im(:,:,3)))/255;

运行 MEX 函数(Sobel 滤波器)

传递归一化图像和阈值。

edgeIm = sobel_mex(gray, 0.7);

显示结果

im3 = repmat(edgeIm, [1 1 3]);
image(im3);

Figure contains an axes. The axes contains an object of type image.

生成独立 C 代码。

codegen -config coder.config('lib') sobel
Code generation successful.

codegen-config coder.config('lib') 选项结合使用生成独立 C 库。默认情况下,为库生成的代码位于文件夹 codegen/lib/sobel/ 中。

检查生成的函数

type codegen/lib/sobel/sobel.c
/*
 * File: sobel.c
 *
 * MATLAB Coder version            : 5.2
 * C/C++ source code generated on  : 13-Mar-2021 21:05:33
 */

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