After repeated investigations and trials over this period of time, in relation to my current problem, I have found out what the problem is and am sharing the exact answer in full.
Run R2022b, win10, test in mingw64 and vc complier.
Conclusion:
- the member function set in the generated coder::array class is not able to convert opencv's Mat type to coder::array<typename T, int N> type in situ, unless you rewrite the inherited class yourself.
- The entry-point function in Matlab, whether declared as `coder.rowMajor;` or specified directly on the command line using the `-codegen` argument `-rowmajor`, does not change the fact that the matlab array is still in coloum-major form (bug).
What can be done to solve this at the moment is to assign values element by element or to use memcpy to copy the data block form to do it.
-------
With test cases:
function outImg = mytest(inImg)%#codegen
% in = coder.typeof(uint8(0),[1000,1000,3],[1,1,0]);% :1000x:1000x3
% codegen -config:lib -c mytest -args in -lang:c++ -report
arguments
inImg uint8
end
outImg = imresize(inImg,0.5);
end
use above comment in command line, generated C++ code,test set() method :
// omit some code
// my custom function, use to convert opencv's mat to matlab matrix
void convertCVToMatrix(cv::Mat &srcImg, int rows, int cols, int channels,
unsigned char dst[])
{
CV_Assert(srcImg.type() == CV_8UC1 || srcImg.type() == CV_8UC3);
size_t elems = rows * cols;
if (channels == 3) {
cv::Mat channels[3];
cv::split(srcImg.t(), channels);
memcpy(dst, channels[2].data,
elems * sizeof(unsigned char)); // copy channel[2] to the red channel
memcpy(dst + elems, channels[1].data,
elems * sizeof(unsigned char)); // green
memcpy(dst + 2 * elems, channels[0].data,
elems * sizeof(unsigned char)); // blue
} else {
srcImg = srcImg.t();
memcpy(dst, srcImg.data, elems * sizeof(unsigned char));
}
}
int main(int, char **)
{
// The initialize function is being called automatically from your entry-point
// function. So, a call to initialize is not included here. Invoke the
// entry-point functions.
// You can call entry-point functions multiple times.
{
coder::array<unsigned char, 3U> inImg;
coder::array<unsigned char, 3U> outImg;
cv::Mat srcImg = cv::imread(
"C:/Program Files/MATLAB/R2022b/toolbox/matlab/imagesci/peppers.png"); // 384*512*3 size
// Since set_size() was set beforehand, then after set srcImg retains the array size of the set method, i.e. the prior set_size method is invalid! Also, if only set is used for the conversion, there is a dimension mismatch problem, i.e. it leads directly to the later calculation in the wrong dimension!
// inImg.set_size(384, 512, 3);
// inImg.set((unsigned char *)dst, srcImg.channels(), srcImg.cols,srcImg.rows);
// The following 2 sentences are the effective and correct way
inImg.set_size(384, 512, 3);
convertCVToMatrix(srcImg, srcImg.rows, srcImg.cols, srcImg.channels(),inImg.data());
// Call the entry-point 'mytest'.
mytest(inImg, outImg);
// output matlab matrix `outImg` to file,so i can read this matrix into matlab to show for debug.
std::cout << " outImg.size:" << outImg.size(0) << "," << outImg.size(1)
<< "," << outImg.size(2) << std::endl;
std::ofstream fid("outImg.txt", std::ios::out);
for (size_t i = 0; i < outImg.size(0); i++) {
if (i != 0) {
fid << std::endl;
}
for (size_t j = 0; j < outImg.size(1); j++) {
fid << (int)outImg.at(i, j, 0) << " "; // only see R channel array.
}
}
fid.close();
}
// Terminate the application.
// You do not need to do this more than one time.
mytest_terminate();
return 0;
}
// End of code generation (main.cpp)
Read the text file output from the above C++ code in matlab:
aa = uint8(readmatrix("outImg.txt"));figure;imshow(aa)
debug found that the only way to display the image correctly was to assign it element by element or my custom conversion function convertCVToMatrix() above.
In addition, due to space limitations above, I have tried specifying `coder.rowMajor` in the matlab entry function or `-rowmajor` on the command line, but this does not work, i.e. the resulting C++ code is still in coloum-major
However, thanks very much to @Alexander Bottema for his positive answer, even if it didn't solve the problem directly.