Search code examples
c#c++opencvemgucv

Rewriting OpenCV C++ to EmguCV C# - how to work with pointers?


I'm trying to convert C++ code written OpenCV 2.x to Emgu.CV in C#.

I have a function in C++:

cv::Mat computeMatXGradient(const cv::Mat &mat) {
    cv::Mat out(mat.rows, mat.cols, CV_64F);
    for (int y = 0; y < mat.rows; ++y) {
        const uchar* Mr = mat.ptr<uchar>(y);
        double* Or = out.ptr<double>(y);
        Or[0] = Mr[1] - Mr[0];
        for (int x = 1; x < mat.cols - 1; ++x) {
            Or[x] = (Mr[x + 1] - Mr[x - 1]) / 2.0;
        }
        Or[mat.cols - 1] = Mr[mat.cols - 1] - Mr[mat.cols - 2];
    }
    return out;
}

How to do the same thing in C# with EmguCV efficiently?

So far - I have this C# code: (I can't test it because a lot of code is missing)

Mat computeMatXGradient(Mat inMat)
{
    Mat outMat = new Mat(inMat.Rows, inMat.Cols, DepthType.Cv64F, inMat.NumberOfChannels);
    for (int y = 0; y < inMat.Rows; ++y)
    {
        // unsafe is required if I'm using pointers
        unsafe {
            byte* Mr = (byte*) inMat.DataPointer;
            double* Or = (double*) outMat.DataPointer;
            Or[0] = Mr[1] - Mr[0];
            for (int x = 1; x < inMat.Cols - 1; ++x)
            {
               Or[x] = (Mr[x + 1] - Mr[x - 1]) / 2.0;
            }
            Or[inMat.Cols - 1] = Mr[inMat.Cols - 1] - Mr[inMat.Cols - 2];
        }
    }
    return outMat;
}

Questions:

  1. Is my C# code correct?

  2. Is there better/more efficient way?


Solution

  • You can try converting inMat to an array inM, then calculating the values you need in another array Or, and finally converting the latter array to the output Mat outMat.

    Note: I considered NumberOfChannels to be 1 as I think this will be always the case.

    Mat computeMatXGradient(Mat inMat)
    {
        int x, y;
        byte[] inM, Mr;
        double[] Or;
        inM = new byte[(int)inMat.Total];
        inMat.CopyTo(inM);
        Mr = new byte[inMat.Cols];
        Or = new double[inMat.Rows * inMat.Cols];
        for (y = 0; y < inMat.Rows; y++)
        {
            Array.Copy(inM, y * inMat.Cols, Mr, 0, inMat.Cols);
            Or[y * inMat.Cols] = Mr[1] - Mr[0];
            for (x = 1; x < inMat.Cols - 1; x++)
               Or[y * inMat.Cols + x] = (Mr[x + 1] - Mr[x - 1]) / 2.0;
            Or[y * inMat.Cols + inMat.Cols - 1] = Mr[inMat.Cols - 1] - Mr[inMat.Cols - 2];
        }
        Mat outMat = new Mat(inMat.Rows, inMat.Cols, DepthType.Cv64F, 1);
        Marshal.Copy(Or, 0, outMat.DataPointer, inMat.Rows * inMat.Cols);
        return outMat;
    }