Use an Example C Main in an Application
This example shows how to build a C executable from MATLAB® code that implements a simple Sobel filter to perform edge detection on images. The executable reads an image from the disk, applies the Sobel filtering algorithm, and then saves the modified image.
The example shows how to generate and modify an example main function that you can use when you build the executable.
Prerequisites
To complete this example, install the following products:
MATLAB
MATLAB Coder™
C compiler (for most platforms, a default C compiler is supplied with MATLAB). For a list of supported compilers, see Supported Compilers.
You can use
mex -setup
to change the default compiler. See Change Default Compiler.
Tutorial Files: Sobel Filter
Open this example to obtain the files for this tutorial: sobel.m
and hello.jpg
.
Description of Tutorial Files
The files you use in this example are:
File Name | File Type | Description |
---|---|---|
sobel.m | Function code | MATLAB implementation of a Sobel filtering algorithm.
sobel.m takes an image (represented as a double matrix) and a
threshold value as inputs. The algorithm detects edges in the image (based on the
threshold value). sobel.m returns a modified image displaying the
edges. |
hello.jpg | Image file | Image that the Sobel filter modifies. |
Run the Sobel Filter on the Image
Read the original image into a MATLAB matrix and display it.
im = imread('hello.jpg');
Display the image as a basis for comparison to the result of the Sobel filter.
image(im);
The Sobel filtering algorithm operates on grayscale images. Convert the color image to an equivalent grayscale image with normalized values (0.0 for black, 1.0 for white).
gray = (0.2989 * double(im(:,:,1)) + 0.5870 * double(im(:,:,2)) + 0.1140 * double(im(:,:,3)))/255;
To run the MATLAB function for the Sobel filter, pass the grayscale image matrix
gray
and a threshold value to the functionsobel
. This example uses 0.7 for a threshold value.edgeIm = sobel(gray, 0.7);
To display the modified image, reformat the matrix
edgeIm
with the functionrepmat
so that you can pass it to theimage
command.im3 = repmat(edgeIm, [1 1 3]); image(im3);
Generate and Test a MEX Function
To test that generated code is functionally equivalent to the original MATLAB code and that run-time errors do not occur, generate a MEX function.
codegen -report sobel
codegen
generates a MEX function namedsobel_mex
in the current working folder.To run the MEX function for the Sobel filter, pass the grayscale image matrix
gray
and a threshold value to the functionsobel_mex
. This example uses 0.7 for a threshold value.edgeImMex = sobel_mex(gray, 0.7);
To display the modified image, reformat the matrix
edgeImMex
with the functionrepmat
so that you can pass it to theimage
command.im3Mex = repmat(edgeImMex, [1 1 3]); image(im3Mex);
This image is the same as the image created using the MATLAB function.
Generate an Example Main Function for sobel.m
Although you can write a custom main function for your application, an example main function provides a template to help you incorporate the generated code.
To generate an example main function for the Sobel filter:
Create a configuration object for a C static library.
cfg = coder.config('lib');
For configuration objects for C/C++ source code, static libraries, dynamic libraries, and executables, the setting
GenerateExampleMain
controls generation of the example main function. The setting is set to'GenerateCodeOnly'
by default, which generates the example main function but does not compile it. For this example, do not change the value of theGenerateExampleMain
setting.Generate a C static library using the configuration object.
codegen -report -config cfg sobel
The generated files for the static library are in the folder
codegen/lib/sobel
. The example main files are in the subfolder
codegen/lib/sobel/examples
.
Copy the Example Main Files
Do not modify the files main.c
and main.h
in the
examples
subfolder. If you do, when you regenerate code, MATLAB
Coder does not regenerate the example main files. It warns you that it detects
changes to the generated files.
Copy the files main.c
and main.h
from the folder
codegen/lib/sobel/examples
to another location. For this example, copy
the files to the current working folder. Modify the files in the new location.
Modify the Generated Example Main Function
The example main function declares and initializes data, including dynamically allocated data, to zero values. It calls entry-point functions with arguments set to zero values, but it does not use values returned from the entry-point functions.
The C main function must meet the requirements of your application. This example modifies the example main function to meet the requirements of the Sobel filter application.
This example modifies the file main.c
so that the Sobel filter
application:
Reads in the grayscale image from a binary file.
Applies the Sobel filtering algorithm.
Saves the modified image to a binary file.
Modify the Function main
Modify the function main
to:
Accept the file containing the grayscale image data and a threshold value as input arguments.
Call the function
main_sobel
with the address of the grayscale image data stream and the threshold value as input arguments.
In the function main
:
Remove the declarations
(void)argc
and(void)argv
.Declare the variable
filename
to hold the name of the binary file containing the grayscale image data.const char *filename;
Declare the variable
threshold
to hold the threshold value.double threshold;
Declare the variable
fd
to hold the address of the grayscale image data that the application reads in fromfilename
.FILE *fd;
Add an
if
statement that checks for three arguments.if (argc != 3) { printf("Expected 2 arguments: filename and threshold\n"); exit(-1); }
Assign the input argument
argv[1]
for the file containing the grayscale image data tofilename
.filename = argv[1];
Assign the input argument
argv[2]
for the threshold value tothreshold
, converting the input from a string to a numeric double.threshold = atof(argv[2]);
Open the file containing the grayscale image data whose name is specified in
filename
. Assign the address of the data stream tofd
.fd = fopen(filename, "rb");
To verify that the executable can open
filename
, write anif
-statement that exits the program if the value offd
isNULL
.if (fd == NULL) { exit(-1); }
Replace the function call for
main_sobel
by callingmain_sobel
with input argumentsfd
andthreshold
.main_sobel(fd, threshold);
Close the grayscale image file after calling
sobel_terminate
.fclose(fd);
Modify the Initialization Function argInit_d1024xd1024_real_T
In the example main file, the function argInit_d1024xd1024_real_T
creates a dynamically allocated variable-size array (emxArray) for the image that you pass
to the Sobel filter. This function initializes the emxArray to a default size and the
elements of the emxArray to 0. It returns the initialized emxArray.
For the Sobel filter application, modify the function to read the grayscale image data from a binary file into the emxArray.
In the function argInit_d1024xd1024_real_T
:
Replace the input argument
void
with the argumentFILE *fd
. This variable points to the grayscale image data that the function reads in.static emxArray_real_T *argInit_d1024xd1024_real_T(FILE *fd)
Change the values of the variables
idx0
andidx1
to match the dimensions of the grayscale image matrixgray
. These variables hold the size values for the dimensions of the emxArray thatargInit_d1024xd1024_real_T
creates.int idx0 = 484; int idx1 = 648;
MATLAB stores matrix data in column-major format, while C stores matrix data in row-major format. Declare the dimensions accordingly.
Change the values of the
emxCreate_real_T
function to the image size.result = emxCreate_real_T(484, 648);
Define a variable
element
to hold the values read in from the grayscale image data.double element;
Change the
for
-loop construct to read data points from the normalized image intoelement
by adding anfread
command to the innerfor
-loop.fread(&element, 1, sizeof(element), fd);
Inside the
for
-loop, assignelement
as the value set for the emxArray data.result->data[idx0 + result->size[0] * idx1] = element;
Write the Function saveImage
The MATLAB function sobel.m
interfaces with MATLAB arrays, but the Sobel filter application interfaces with binary
files.
To save the image modified by the Sobel filtering algorithm to a binary file, create a
function saveImage
. The function saveImage
writes
data from an emxArray into a binary file. It uses a construction that is similar to the
one used by the function argInit_d1024xd1024_real_T
.
In the file main.c
:
Define the function
saveImage
that takes the address of emxArrayedgeImage
as an input and has output type void.static void saveImage(emxArray_uint8_T *edgeImage) { }
Define the variables
idx0
andidx1
like they are defined in the functionargInit_d1024xd1024_real_T
.int idx; int idx1;
Define the variable
element
to store data read from the emxArray.uint8_T element;
Open a binary file
edge.bin
for writing the modified image. Assign the address ofedge.bin
toFILE *fd
.FILE *fd = fopen("edge.bin", "wb");
To verify that the executable can open
edge.bin
, write anif
-statement that exits the program if the value offd
isNULL
.if (fd == NULL) { exit(-1); }
Write a nested
for
-loop construct like the one in the functionargInit_d1024xd1024_real_T
.for (idx0 = 0; idx0 < edgeImage->size[0U]; idx0++) { for (idx1 = 0; idx1 < edgeImage->size[1U]; idx1++) { } }
Inside the inner
for
-loop, assign the values from the modified image data toelement
.element = edgeImage->data[idx0 + edgeImage->size[0] * idx1];
After the assignment for
element
, write the value fromelement
to the fileedge.bin
.fwrite(&element, 1, sizeof(element), fd);
After the
for
-loop construct, closefd
.fclose(fd);
Modify the Function main_sobel
In the example main function, the function main_sobel
creates
emxArrays for the data for the grayscale and modified images. It calls the function
argInit_d1024xd1024_real_T
to initialize the emxArray for the
grayscale image. main_sobel
passes both emxArrays and the threshold
value of 0 that the initialization function argInit_real_T
returns to
the function sobel
. When the function main_sobel
ends, it discards the result of the function sobel
.
For the Sobel filter application, modify the function main_sobel
to:
Take the address of the grayscale image data and the threshold value as inputs.
Read the data from the address using
argInit_d1024xd1024_real_T
.Pass the data to the Sobel filtering algorithm with the threshold value
threshold
.Save the result using
saveImage
.
In the function main_sobel
:
Replace the input arguments to the function with the arguments
FILE *fd
anddouble threshold
.static void main_sobel(FILE *fd, double threshold)
Pass the input argument
fd
to the function call forargInit_d1024xd1024_real_T
.originalImage = argInit_d1024xd1024_real_T(fd);
Replace the threshold value input in the function call to
sobel
withthreshold
.sobel(originalImage, threshold, edgeImage);
After calling the function
sobel
, call the functionsaveImage
with the inputedgeImage
.saveImage(edgeImage);
Modify the Function Declarations
To match the changes that you made to the function definitions, make the following changes to the function declarations:
Change the input of the function
*argInit_d1024xd1024_real_T
toFILE *fd
.static emxArray_real_T *argInit_d1024xd1024_real_T(FILE *fd);
Change the inputs of the function
main_sobel
toFILE *fd
anddouble threshold
.static void main_sobel(FILE *fd, double threshold);
Add the function
saveImage
.static void saveImage(emxArray_uint8_T *edgeImage);
Modify the Include Files
For input/output functions that you use in main.c
, add the header
file stdio.h
to the included files list.
#include <stdio.h>
Contents of Modified File main.c
Generate the Sobel Filter Application
Navigate to the working folder if you are not currently in it.
Create a configuration object for a C standalone executable.
cfg = coder.config('exe');
Generate a C standalone executable for the Sobel filter using the configuration object and the modified main function.
codegen -report -config cfg sobel main.c main.h
By default, if you are running MATLAB on a Windows® platform, the executable sobel.exe
is generated in the
current working folder. If you are running MATLAB on a platform other than Windows, the file extension is the corresponding extension for that platform. By
default, the code generated for the executable is in the folder
codegen/exe/sobel
.
Run the Sobel Filter Application
Create the MATLAB matrix
gray
if it is not currently in your MATLAB workspace:im = imread('hello.jpg');
gray = (0.2989 * double(im(:,:,1)) + 0.5870 * double(im(:,:,2)) + 0.1140 * double(im(:,:,3)))/255;
Write the matrix
gray
into a binary file using thefopen
andfwrite
commands. The application reads in this binary file.fid = fopen('gray.bin', 'w'); fwrite(fid, gray, 'double'); fclose(fid);
Run the executable, passing to it the file
gray.bin
and the threshold value 0.7.To run the example in MATLAB on a Windows platform:
system('sobel.exe gray.bin 0.7');
The executable generates the file
edge.bin
.
Display the Resulting Image
Read the file
edge.bin
into a MATLAB matrixedgeImExe
using thefopen
andfread
commands.fd = fopen('edge.bin', 'r'); edgeImExe = fread(fd, size(gray), 'uint8'); fclose(fd);
Pass the matrix
edgeImExe
to the functionrepmat
and display the image.im3Exe = repmat(edgeImExe, [1 1 3]); image(im3Exe);
The image matches the images from the MATLAB and MEX functions.