【问题标题】:running opencv code with matlab via mex fails while on VisualStudio it works通过 mex 使用 matlab 运行 opencv 代码失败,而在 VisualStudio 上它可以工作
【发布时间】:2014-04-07 23:38:16
【问题描述】:

我想从图像中提取一些 harriscorners 并获取 FREAK 描述符。这是我尝试这样做的方法: (传递的变量是全局定义的。)

void computeFeatures(cv::Mat &src, std::vector<cv::KeyPoint> &keypoints, cv::Mat &desc ) {
    cv::Mat featureSpace;
    featureSpace = cv::Mat::zeros( src.size(), CV_32FC1 );

    //- Detector parameters
    int blockSize = 3;
    int apertureSize = 3;
    double k = 0.04;

    //- Detecting corners
    cornerHarris( src, featureSpace, blockSize, apertureSize, k, cv::BORDER_DEFAULT );

    //- Thresholding featureSpace
    keypoints.clear();
    nonMaximumSuppression(featureSpace, keypoints, param.nms_n); 

    //- compute FREAK-descriptor
    cv::FREAK freak(false, false, 22.0f, 4); 
    freak.compute(src, keypoints, desc);
}

我可以通过 mex 使用 Visual Studio 12 和 Matlab R2013b 编译它。当我将它作为“独立”(.exe)运行时,它工作得很好。当我尝试通过 Matlab 执行它时,它会失败并显示以下消息:

MATLAB.exe 中发生缓冲区溢出,损坏了 程序的内部状态。按 Break 调试程序或继续 终止程序。

我混合了调试选项“-g”并将 VisualStudio 附加到 Matlab 以便能够更接近错误: 在nonMaximumSuppression() 之后,当我跳转到freak.compute() 时,关键点的大小为233,其大小突然变为83,并存储了“随机”值。 实际错误在KeyPointsFilter::runByKeypointSize 中,此时应删除关键点。

在 keypoint.cpp 第 256 行:

void KeyPointsFilter::runByKeypointSize( vector<KeyPoint>& keypoints, float minSize, float maxSize )
{
    CV_Assert( minSize >= 0 );
    CV_Assert( maxSize >= 0);
    CV_Assert( minSize <= maxSize );

    keypoints.erase( std::remove_if(keypoints.begin(), keypoints.end(), SizePredicate(minSize, maxSize)),
                     keypoints.end() );
}

我在传递关键点向量时是否犯了一些错误?有没有人遇到过类似的问题?

编辑:

这是带有附加库“opencv_matlab.hpp”的 mex 文件,取自 MatlabCentral

#include "opencv_matlab.hpp"

void mexFunction (int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) {

    // read command
    char command[128];
    mxGetString(prhs[0],command,128);

    if (!strcmp(command,"push") || !strcmp(command,"replace")) {

        // check arguments
        if (nrhs!=1+1 && nrhs!=1+2)
          mexErrMsgTxt("1 or 2 inputs required (I1=left image,I2=right image).");
        if (!mxIsUint8(prhs[1]) || mxGetNumberOfDimensions(prhs[1])!=2)
          mexErrMsgTxt("Input I1 (left image) must be a uint8_t matrix.");

        // determine input/output image properties
        const int *dims1    = mxGetDimensions(prhs[1]);
        const int nDims1    = mxGetNumberOfDimensions(prhs[1]);
        const int rows1     = dims1[0];
        const int cols1     = dims1[1];
        const int channels1 = (nDims1 == 3 ? dims1[2] : 1);

        // Allocate, copy, and convert the input image
        // @note: input is double
        cv::Mat I1_ = cv::Mat::zeros(cv::Size(cols1, rows1), CV_8UC(channels1));
        om::copyMatrixToOpencv<uchar>((unsigned char*)mxGetPr(prhs[1]), I1_);

        // push back single image
        if (nrhs==1+1) {

          // compute features and put them to ring buffer
            pushBack(I1_,!strcmp(command,"replace"));

        // push back stereo image pair
        } else {

          if (!mxIsUint8(prhs[2]) || mxGetNumberOfDimensions(prhs[2])!=2)
            mexErrMsgTxt("Input I2 (right image) must be a uint8_t matrix.");

          // determine input/output image properties
          const int *dims2    = mxGetDimensions(prhs[2]);
          const int nDims2    = mxGetNumberOfDimensions(prhs[2]);
          const int rows2     = dims2[0];
          const int cols2     = dims2[1];
          const int channels2 = (nDims2 == 3 ? dims2[2] : 1);

          // Allocate, copy, and convert the input image
          // @note: input is double
          cv::Mat I2_ = cv::Mat::zeros(cv::Size(cols2, rows2), CV_8UC(channels2));
          om::copyMatrixToOpencv<uchar>((unsigned char*)mxGetPr(prhs[2]), I2_);

          // check image size
          if (dims1_[0]!=dims2_[0] || dims1_[1]!=dims2_[1])
            mexErrMsgTxt("Input I1 and I2 must be images of same size.");

          // compute features and put them to ring buffer
          pushBack(I1_,I2_,!strcmp(command,"replace"));
        }
    }else {
    mexPrintf("Unknown command: %s\n",command);
  }
}

这是主 cpp 项目的附加部分。

std::vector<cv::KeyPoint> k1c1, k2c1, k1p1, k2p1; //KeyPoints
cv::Mat d1c1, d2c1, d1p1, d2p1; //descriptors

void pushBack (cv::Mat &I1,cv::Mat &I2,const bool replace) {
    // sanity check
    if (I1.empty()) {
        cerr << "ERROR: Image empty!" << endl;
        return;
    }

    if (replace) {
        //if (!k1c1.empty()) 
        k1c1.clear(); k2c1.clear();
        d1c1.release(); d2c1.release();
    } else {
        k1p1.clear(); k2p1.clear();
        d1p1.release(); d2p1.release();

        k1p1 = k1c1; k2p1 = k2c1;
        d1c1.copyTo(d1p1); d2c1.copyTo(d2p1);

        k1c1.clear(); k2c1.clear();
        d1c1.release(); d2c1.release();
    }

    // compute new features for current frame
    computeFeatures(I1,k1c1,d1c1); 
    if (!I2.empty())
        computeFeatures(I2,k2c1,d2c1);
}

这是我从 Matlab 调用 mex 文件的方式

I1p = imread('\I1.bmp');
I2p = imread('\I2.bmp');
harris_freak('push',I1p,I2p);

希望这会有所帮助...

【问题讨论】:

  • 你能发布 mex 文件吗?
  • 请添加允许重现问题的代码。

标签: c++ visual-studio matlab opencv mex


【解决方案1】:

我希望这是回答我自己的问题的正确方法。

几天后,我找到了一种解决方法。 我没有在 Matlab 中构建 mex 文件,这会导致上述错误,我在 Visual Studio 中构建了它,说明来自 here。 现在一切正常。

不知道怎么用 matlab 做这件事有点困扰我,但是嘿,也许有人还有一个想法。

感谢评论者花时间浏览我的问题!

【讨论】:

    【解决方案2】:

    如果您有计算机视觉系统工具箱,则不需要 mex。它包括用于检测Harris角的detectHarrisFeatures函数和可以计算FREAK描述符的extractFeatures函数。

    【讨论】:

      猜你喜欢
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-08
      • 1970-01-01
      • 1970-01-01
      • 2011-04-24
      • 2013-01-13
      相关资源
      最近更新 更多