I want to use the OpenCV function cvtColor to change and image from RGB to Grayscale using a S-Function in Simulink, like this:
In order for the input to be used with OpenCV it needs to be converted into cv::Mat. I found that this can be done with the OpenCV Interface C++ API, but I do not know exactly how to do it.
My knowledge of S-Functions is limited but, as far as I know, the conversion needs to be done inside the mdlOutputs method. Something similar to this:
static void mdlOutputs(SimStruct *S, int_T tid)
{
const uint8_T *u0 = (const uint8_T*) ssGetInputPortSignal(S,0);
uint8_T *y0 = (uint8_T*) ssGetOutputPortRealSignal(S,0);
void ocvMxArrayToImage_uint8(const mxArray *u0, cv::Mat &colourImage);
cv::cvtColor(colourImage,grayImage,CV_RGB2GRAY);
y0 *ocvMxArrayFromImage_uint8(const cv::Mat &grayImage);
}
Am I on the right track? Do you know where can I found some examples of this?
Thank you
Edit:
Thanks a lot for your comment @Phil Goddard. With your guidance I am now able to compile the S-function. Now I have a different problem. Every time I try to run Simulink, the program crashes I get the following error:
Fault Count: 1
Assertion in void __cdecl anonymous-namespace'::error(const struct
anonymous-namespace'::header *const ,const unsigned __int64,const void const ,const unsigned __int64,const class boost::basic_format,class std::allocator > &) at b:\matlab\foundation_libraries\src\fl\mem\alignment.cpp line 323: The pointer passed to 'vector_check' is invalid and does not appear to have come from any of the following routines: vector_malloc, vector_calloc, vector_realloc mxMalloc, mxCalloc*, mxRealloc*
This suggests one of the following has happened:
- the pointer has already been freed
- the pointer came from an incompatible allocator (e.g. new, malloc, utMalloc)
- the pointer didn't come from any allocator (e.g. the stack, uninitialized memory)
- a memory corruption destroyed the pointer or its header
I have updated the code as well like this:
static void mdlOutputs(SimStruct *S, int_T tid)
{
uint8_T *u0 = (uint8_T*) ssGetInputPortSignal( S,0);
uint8_T *y0 = (uint8_T*) ssGetOutputPortSignal( S,0);
// channels = Number of dimensions; size = Dimensions
mxArray *A = mxCreateNumericArray(channels,size,mxUINT8_CLASS,mxREAL);
mxSetData(A,u0);
cv::Ptr<cv::Mat> imgOriginal = ocvMxArrayToImage_uint8(A, true);
// Width & height = Dimensions input image
cv::Mat imgGray(width,height,CV_8UC2);
cv::cvtColor(*imgOriginal,imgGray,CV_BGR2GRAY);
mxArray *B = mxCreateNumericArray(channels,size,mxUINT8_CLASS,mxREAL);
B = ocvMxArrayFromImage_uint8(imgGray);
y0 = (uint8_T *)mxGetData(B);
} /* end mdlOutputs */
Any idea of what is wrong?