我正在编写一个调用conv2
函数的mex文件。此mex
文件将获得大小为(M, N)
的图片,并使用conv2
多次应用卷积。
#include "mex.h"
void myconv( mxArray *Ain, mxArray *Kernel, mxArray *&Aout )
{
mxArray *rhs[3];
rhs[0] = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
rhs[1] = mxCreateNumericMatrix( 0, 0, mxDOUBLE_CLASS, mxREAL );
rhs[2] = mxCreateString ( "same" );
double *ainPtr = mxGetPr( Ain );
mxSetPr( rhs[0], ainPtr );
mxSetM ( rhs[0], mxGetM(Ain) );
mxSetN ( rhs[0], mxGetM(Ain) );
double *kernelPtr = mxGetPr( Kernel );
mxSetPr( rhs[1], kernelPtr );
mxSetM ( rhs[1], mxGetM(Kernel) );
mxSetN ( rhs[1], mxGetN(Kernel) );
mexCallMATLAB(1, &Aout, 3, rhs, "conv2");
mxSetPr( rhs[0], NULL );
mxSetPr( rhs[1], NULL );
}
void myconv_combine( mxArray *Ain, mxArray *&Aout )
{
mxArray *mask = mxCreateDoubleMatrix( 1, 5, mxREAL );
double *maskPtr = mxGetPr( mask );
maskPtr[0] = 0.05;
maskPtr[1] = 0.25;
maskPtr[2] = 0.4;
maskPtr[3] = 0.25;
maskPtr[4] = 0.05;
mxArray *maskTranspose = mxCreateDoubleMatrix( 0, 0, mxREAL );
mxSetPr( maskTranspose, maskPtr );
mxSetM ( maskTranspose, mxGetN(mask) );
mxSetN ( maskTranspose, mxGetM(mask) );
mxArray *AinConvolved = mxCreateDoubleMatrix( (mwSize)mxGetM(Ain), (mwSize)mxGetN(Ain), mxREAL );
double *AinConvolvedPtr = mxGetPr( AinConvolved );
myconv( Ain, mask, AinConvolved );
// Some modifications.
mxArray *Temp = mxCreateDoubleMatrix( (mwSize)mxGetM(Ain), (mwSize)mxGetN(Ain), mxREAL );
double *TempPtr = mxGetPr( Temp );
for( int i = 0; i < (mwSize)mxGetM(Ain)*(mwSize)mxGetN(Ain); i++ )
TempPtr[ i ] = 2.0*AinConvolvedPtr[ i ];
// Some other convolution.
mxArray *TempConvolved = mxCreateDoubleMatrix( (mwSize)mxGetM(Ain), (mwSize)mxGetN(Ain), mxREAL );
double *TempConvolvedPtr = mxGetPr( TempConvolved );
myconv( Temp, maskTranspose, TempConvolved );
// Some other modifications.
double *AoutPtr = mxGetPr( Aout );
for( int i = 0; i < (mwSize)mxGetM(Ain)*(mwSize)mxGetN(Ain); i++ )
AoutPtr[ i ] = 2.0*TempConvolvedPtr[ i ];
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mxArray *Ain = mxCreateDoubleMatrix( 100, 100, mxREAL );
mxArray *Aout = mxCreateDoubleMatrix( 100, 100, mxREAL );
myconv_combine( Ain, Aout );
}
在我的实际代码中,当它到达行时:
myconv( Temp, maskTranspose, TempConvolved );
MATLAB崩溃,我不知道为什么会发生这种情况,不幸的是我无法在上面提供的示例代码中复制相同的错误。在我的实际代码中,图像按行成功卷积:
myconv( Ain, mask, AinConvolved );
但是,只要它想要应用第二个卷积:
myconv( Temp, maskTranspose, TempConvolved );
崩溃,当我调试它时,会在mexCallMATLAB
函数上调用myconv
时发生。 Temp
/ TempConvolved
和Ain
/ AinConvolved
之间的区别是什么导致前者在mexCallMATLAB
时崩溃?
有人可以帮我解决这个问题吗?
答案 0 :(得分:1)
重用数据缓冲区
重用mxArray *mask
mxArray *maskTransposed
的数据指针是一个麻烦,因为MATLAB具有严格的引用计数机制,因为共享数据数组是MATLAB内存优化的重要组成部分。相反,使用mxDuplicateArray
复制整个内容:
mxArray *maskTranspose = mxDuplicateArray(mask);
有一个未记录的mxCreateSharedDataCopy
模仿MATLAB的懒惰复制机制,但对于5个元素的数组来说真的有点过分。
在mxArray
mexCallMATLAB
初始化
另外,在致电mxArray *AinConvolved
之前,请不要忘记初始化mexCallMATLAB
。只需传递一个NULL指针,它就会为你创建它。如果你不是,它只会擦除旧的(将其发送到垃圾收集)并为conv2
的输出创建一个新的。这让我想起这表明你的代码中存在这个问题:
mxArray *AinConvolved = mxCreateDoubleMatrix(mxGetM(Ain), mxGetN(Ain), mxREAL);
double *AinConvolvedPtr0 = mxGetPr(AinConvolved);
myconv(Ain, mask, AinConvolved);
double *AinConvolvedPtr = mxGetPr(AinConvolved);
mexPrintf("%p\n%p\n", AinConvolvedPtr0, AinConvolvedPtr);
MATLAB输出:
00000000B852FA20
0000000026B8EB00
正如您所看到的,如果您在使用mxGetPr
之前尝试使用mexCallMATLAB
附带的指针,则可能使用了错误的数据,可能已经释放了内存..
使用imfilter
另请注意,如果您有imfilter
,则不需要实现可分离卷积,因为它内置了该功能。只需查看imfilter.m
并注意{{ 1}}功能。请参阅here for more information。
试试看,我会发布一个测试。