Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to translate OpenCV-C++ code, containing pointers, to JAVA?

I am currently translating a bit of c++ code to Java, for an Android-application. I have stumbled upon a tricky bit of c++ code however (also c++ is not my main language). Below is the c++-code. This function calculates the image gradients in an openCV imageFrame (in gray scale).

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];
  }
}

In this snippet, I don't know how to interpret the first two lines in the first loop:

    const uchar *Mr = mat.ptr<uchar>(y);
    double *Or = out.ptr<double>(y);

What is being done here, and how could I translate it to Java-code? I have looked into the 'mat.ptr<>()' function, but that wasn't very helpful either. (Documentation can be found here.) Basic information about pointers (like here) I've already read into, but I still don't get how to read the lines above. Apart from the pointers used, I'm also not quite sure how to handle the 'uchar'-type that is being used. How does that translate to Java?

The entire code can be found here.

I've already looked into ways of implementing the Gradient-function of Matlab from scratch, but that seems a lot harder. (Yes, there are already topics about that (e.x. here), but this thread doesn't provide an actual answer on how to do it.)

I really hope someone can explain how to handle the c++-structures above, in Java. I did all the possible research I could do so far, but I just can't get my head around how to do it in Java. Thanks in advance!

EDIT; In the end I've been able to get it working by just using a double for-loop. The code is below. It is much less efficient however. On a galaxy tab4 the process-rate is only about 1 frame per second. I wasn't expecting to get perfect results, but I had hoped it would be a bit faster. Does anyone know if the code below can be done more efficiently? Even the smallest change will be great, because there are like six of those double for-loops in the algorithm.

private static Mat computeXGradient (Mat mat) {
    //Mat output = new Mat(mat.rows(), mat.cols(), CvType.CV_64F);
    Mat output = new Mat(mat.rows(), mat.cols(), CvType.CV_32F);
    for (byte y = 0; y < mat.rows(); ++y) {
        Mat mr = mat.row(y);
        output.put(y,0, mr.get(0,1)[0] - mr.get(0,0)[0]);
        for (byte x = 1; x < mat.cols() - 1; ++x) {
            output.put(y,x, (mr.get(0,x+1)[0] - mr.get(0,x-1)[0])/2.0);
        }
    }
    return output;
}

I already implemented multi-threading (with actual forcing of using more processors), and as you can see I also scaled down the size of the Mat-objects I am working with.

EDIT; after adjusting the resolution, the frame-rate went up to a very acceptable level. Hopefully this change will not affect the spatial performance too much, but we will see about that.

like image 226
Mastermind1992 Avatar asked Nov 10 '22 15:11

Mastermind1992


1 Answers

mat.ptr(y) fetches row y from the matrix.

Likewise, out.ptr(y) fetches row y from the output matrix.

As far as translation, you might either create a Row class in Java, or just return an array from the ptr function.

If you don't have the Matrix classes already provided, you might make Row a generic type, like this library did. (eg. Row<Integer>)

uchar (unsigned char) roughly translates to byte in Java. It's an 8 bit (signed) integer value. If you want to ensure you can use the entire 0-255 range, use an int instead.

like image 90
Barett Avatar answered Nov 15 '22 06:11

Barett