【发布时间】: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 魔法。