【问题标题】:How to translate OpenCV-C++ code, containing pointers, to JAVA?如何将包含指针的 OpenCV-C++ 代码翻译成 JAVA?
【发布时间】:2015-06-25 13:26:19
【问题描述】:

我目前正在将一些 c++ 代码翻译成 Java,用于 Android 应用程序。然而,我偶然发现了一些棘手的 c++ 代码(c++ 也不是我的主要语言)。下面是c++代码。此函数计算 openCV imageFrame 中的图像梯度(灰度)。

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

在这个sn-p中,我不知道如何解释第一个循环中的前两行:

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

这里正在做什么,我如何将其转换为 Java 代码?我已经研究了“mat.ptr()”函数,但这也不是很有帮助。 (文档可以在here 找到。)关于指针的基本信息(如here)我已经读过,但我仍然不明白如何阅读上面的行。除了使用的指针之外,我也不太确定如何处理正在使用的 'uchar' 类型。这如何转化为 Java?

完整代码可以在here找到。

我已经从头开始研究了实现 Matlab 的梯度函数的方法,但这似乎要困难得多。 (是的,已经有关于这个的话题(例如here),但是这个帖子没有提供关于如何做到这一点的实际答案。)

我真的希望有人能解释如何用 Java 处理上面的 c++ 结构。到目前为止,我做了所有我能做的研究,但我就是不知道如何在 Java 中做到这一点。 提前致谢!

编辑;最后,我只需使用双 for 循环就可以让它工作。代码如下。然而,它的效率要低得多。在 Galaxy Tab4 上,处理速率仅为每秒约 1 帧。我没想到会得到完美的结果,但我希望它会快一点。有谁知道下面的代码是否可以更有效地完成?即使是最小的变化也会很棒,因为算法中有大约六个这样的双 for 循环。

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

我已经实现了多线程(实际上强制使用更多的处理器),正如你所见,我还缩小了我正在使用的 Mat 对象的大小。

编辑;调整分辨率后,帧率上升到非常可接受的水平。希望这种变化不会对空间性能产生太大影响,但我们会看到这一点。

【问题讨论】:

  • 顺便说一句,Sobel 可以从纯 java 中获得,你可能不需要任何 jni 魔法。

标签: java android c++ opencv


【解决方案1】:

mat.ptr(y) 从矩阵中取出第 y 行。

同样,out.ptr(y) 从输出矩阵中获取第 y 行。

就翻译而言,您可以在 Java 中创建一个 Row 类,或者只从 ptr 函数返回一个数组。

如果您还没有提供 Matrix 类,您可以将 Row 设为泛型类型,就像这个库所做的那样。 (例如Row&lt;Integer&gt;

uchar(无符号字符)在 Java 中大致转换为 byte。这是一个 8 位(有符号)整数值。如果要确保可以使用整个 0-255 范围,请改用 int。

【讨论】:

  • 为惊喜做好准备。 uchar 不会将 1:1 转换为 Java 的字节,这是一个有符号(!)的 8 位数量。
  • 感谢您的回答!最后结果证明我可以做一个双 for 循环并获取存储在 (y,x) 的数组中的第一个条目。你的回答帮助我到达那里;)然而,它在 JAVA 中的效率确实非常低。这可能与为什么要在 C(++) 中使用指针有关吗?它们更有效率吗?
  • 很难说为什么你在 Java 中的双 for 循环似乎不如 C++ 中的等效代码而不看代码。语言本身没有任何隐含的内容会导致显着差异。
  • 嗨,我在原始帖子中添加了我在 Java 中提出的 for 循环。我应该提到我正在 Android(galaxy tab4)设备上运行我的代码,并且我正在构建一个眼动仪。但是,我仍然期望得到比现在更好的结果(0.5 fps)。例如,我知道,在 2011 年进行的一项研究中,类似的算法在 iPad2 上达到了大约 1.5fps。
猜你喜欢
  • 1970-01-01
  • 2016-08-04
  • 2014-01-06
  • 1970-01-01
  • 1970-01-01
  • 2021-10-17
  • 2015-11-25
  • 1970-01-01
相关资源
最近更新 更多