Generated MEX function from a custom C code, but gives empty output.
4 views (last 30 days)
Show older comments
Hello, I'm trying to generate a MEX function based on the line segment detector (LSD) that is available in this repository: theWorldCreator/LSD: a Line Segment Detector (github.com). The function I'd like to convert looks like below:
double * lsd(int * n_out, double * img, int X, int Y);
Here are short descriptions for the input and output of the function:
- n_out: Pointer to an int where LSD will store the number of line segments detected.
- img: Pointer to input image data. It must be an array of doubles of size X x Y, and the pixel at coordinates (x,y) is obtained by img[x+y*X].
- X: the number of columns of a given image
- Y: the number of rows of a given image.
- Returns: A double array of size 7 x n_out, containing the list of line segments detected.
The arguments n_out, X, and Y are needed to preallocate arrays in C, but we don't necessarily need it when running it on MATLAB. Therefore, I created an entry point function that calls the LSD function but with img as an only input argument:
function out = m_lsd(img) %#codegen
% Entry point function
% Some parameters
n_out = int32(5000); % number of detected segments will be around 5000 at most.
imsize = int32(size(img));
X = imsize(1);
Y = imsize(2);
% Pre-allocate output array
out = coder.nullcopy(zeros(7, n_out));
% Generate C Code using existing C Code:
coder.updateBuildInfo('addSourceFiles', 'lsd.c');
coder.updateBuildInfo('addIncludePaths', '/path/to/my/folder');
fprintf('Running LSD code written in C ... \n\n');
coder.ceval('lsd', coder.ref(n_out), coder.ref(img), X, Y);
end
I also wrote a build function that looks like below:
function build(target)
% Entry-point function
entryPoint = 'm_lsd'; % using a MATLAB function "m_lsd.m"
% Input is an array of type double with variable size
arg = coder.typeof(double(0), [Inf, Inf]);
% Configuration object
cfg = coder.config(target);
% Custom source files and source code
cfg.CustomSource = 'lsd.c';
cfg.CustomSourceCode = sprintf('%s\n\r%s\n\r%s\n\r%s\n\r%s\n\r%s', ...
'#include <stdio.h>',...
'#include <math.h>',...
'#include <limits.h>',...
'#include <float.h>',...
'#include "lsd.h"');
% Generate and launch report
cfg.GenerateReport = true;
cfg.LaunchReport = false;
% Generate code
codegen(entryPoint, '-args', {arg}, '-config', cfg);
end
I built the mex function by running "build mex" and I got a MEX function without any error message. However, when I apply it to an example image, the MEX function only returns a zero matrix. Here is an example application of the mex function:
grayImg = double(imread('cameraman.tif'));
segs = m_lsd_mex(grayImg); % --> Gives a zero matrix, even though lsd.c returned meaningful reuslts
Could anyone advise me where I'm doing wrong? Thank you for your help...!
0 Comments
Answers (1)
Alan
on 4 Jul 2024
Edited: Alan
on 4 Jul 2024
Hi Daigo,
You could use the "mex" command instead of "codegen" command to generate the mex file. You could include a header file named “mex.h” inside “lsd.c” and then insert a function named “mexFunction” at the end of the file as follows:
void mexFunction(
int nargout,
mxArray *pargout [ ],
int nargin,
const mxArray *pargin [ ]
) {
// Extract the inputs
int n_out = (int)mxGetScalar(pargin[0]);
double* img = mxGetPr(pargin[1]);
int X = (int)mxGetScalar(pargin[2]);
int Y = (int)mxGetScalar(pargin[3]);
// Call the 'lsd' function
double* result = lsd(&n_out, img, X, Y);
// Create the output array
mwSize dims[2] = { (mwSize)n_out, 1 };
pargout[0] = mxCreateNumericArray(2, dims, mxDOUBLE_CLASS, mxREAL);
// Copy the result to the output array
double* outData = mxGetPr(pargout[0]);
for (int i = 0; i < n_out; ++i) {
outData[i] = result[i];
}
// Free the result if it was dynamically allocated
free(result);
}
The above function controls how the data is passed from MATLAB to C, processed and sent back to MATLAB. The arguments “pargout” and “pargin” contains the inputs from the MATLAB side, and the number of inputs and outputs are stored in “nargin” and “nargout” respectively. It is critical to name the function exactly “mexFunction” as it is treated by the “mex” command like a “main” function in C or C++.
After this modification, a mex file can be generated with the following command:
mex('lsd.c', '-output', 'm_lsd_mex');
The mex function can be called from MATLAB with a slight modification to your call:
grayImg = double(imread('cameraman.tif'));
n_out = 5000;
X = size(grayImg, 2); % The X-Y dimensions of the array have to swapped to get the image dimensions
Y = size(grayImg, 1);
segs = m_lsd_mex(n_out, grayImg, X, Y);
I had followed the above steps and got a 97x1 array as an output, which I hope is your desired output.
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!