1

I want to use the OpenCV function cvtColor to change and image from RGB to Grayscale using a S-Function in Simulink, like this:

Simulink Image

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 structanonymous-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?

Onion
  • 11
  • 4
  • Your data types are most wrong. `ssGetOutputPortRealSignal` returns a `real_T` (which is normally a `double`). You need to use `ssGetOutputPortSignal`. You have `u0` as a `uint8_T`, but the first input to `ocvMxArrayToImage` requires an `mxArray` and casting as you have done is nonsense. You need to create an `mxArray` and and write `u0` to it, before using it as the input. `ocvMxArrayFromImage_uint8` returns an `mxArray` but you are trying to poke it into a `uint8_T`. – Phil Goddard Apr 27 '17 at 15:21

0 Answers0