8

我正在尝试使用 OpenCv4Android 为 Android 设备编写一些应用程序。早些时候,我使用的是 Android NDK 和 C++ 本机代码。但这种技术并不是很清楚。所以我切换到最新的 Java API 以及 OpenCv 2.4.4 版本。

我能够编写简单的程序并运行示例。但是,当我尝试为模型 POSE 估计、相机校准例程等高级问题编写一些代码时,我遇到了这种非常奇怪的困惑。一些在 C++ API 中名称非常直观的数据类型在它们的 Java 对应物中并不真正适合。因此,将我的功能从 C++ 移植到 Java 时,我面临着巨大的困难。我在这些功能中面临着完全的困惑

  • Point2f(在 C++ 中)- MatOfPoint2f(在 Java 中)
  • Point3f(在 C++ 中)- MatOfPoint3f(在 Java 中)
  • Point2(在 Java 中)
  • Point3(Java 中)

请帮助我理解 OpenCv Java 中使用的术语及其与 C++ 的类比。

另外,请给我一些参考,在哪里给出这些术语的清晰和清晰的描述(我尝试观看提供的帮助,但它对我没有多大帮助,因为它对于 C++ 和 Java 有点相似)。

4

1 回答 1

6

引用安德烈·帕夫连科的话:

引入了 MatOfXxx 类(例如 MatOfPoint)以避免在 Java 和本机内存之间冗余复制中间数据。例如,您可以通过一个 OpenCV 函数获得大量点,然后将其传递给另一个。

在 C++ 中,我们为此使用 std::vector。但是在 Java 中使用 ArrayList 会导致在返回这些点时将所有点数据从本机 OpenCV 级别复制到 Java,并在使用它们调用下一个 OpenCV 函数时将它们复制回来。因此,为了提高效率,我们在这种情况下转而使用 MatOfPoint 类,这是一种 1n 或 n1 维的 Mat,在每个元素中保留一个 Point(即 CV_32SC2 或 CV_64FC2 类型)。

您可能知道,Mat 将所有数据保留在本机级别,因此此类对象可以在 OpenCV 调用之间传递而无需数据复制。但是,如果在您的 Java 代码中,您需要直接访问实际的 Points 数据,则可以使用 toArray() 和 fromArray 方法将数据显式传输到 Java 或从 Java 传输数据。

例如,要创建一个包含与现有 MatOfKeyPoint 中的点相对应的点的 MatOfPoint2f,您需要:

  • 通过 MatOfKeyPoint.toArray() 将 KeyPoints 加载到 Java
  • 遍历 KeyPoint[] 并创建一个对应的 Point[] (所有的 cv::Point、cv::Point2f 和 cv::Point2d 在 Java 中都表示为 org.opencv.core.Point)
  • 使用 MatOfPoint2f.fromArray() 或 c-tor MatOfPoint2f(Point...pa) 将您的点置于本机级别

至于 C++ 与 Java 类型的对应关系:

vector<Point>    : MatOfPoint
vector<Point2f>  : MatOfPoint2f
vector<Point3i>  : MatOfPoint3
vector<Point3f>  : MatOfPoint3f
vector<KeyPoint> : MatOfKeyPoint
vector<DMatch>   : MatOfDMatch
vector<Rect>     : MatOfRect
vector<uchar>    : MatOfByte
vector<char>     : MatOfByte
vector<int>      : MatOfInt
vector<float>    : MatOfFloat
vector<double>   : MatOfDouble
vector<Vec4i>    : MatOfInt4
vector<Vec4f>    : MatOfFloat4
于 2014-02-21T21:52:31.183 回答