Java OpenCV 阿鲁科垫

Java OpenCV Aruco Mat

我正在尝试将 Android 相机预览图像输入 OpenCV 以检测 Aruco 代码。根据之前的工作,目前的流程如下:

  1. 我有一个 YUV Image.Plane
  2. 我把它喂给ZXing PlanarYUVLuminanceSource
  3. 对此我调用 getMatrix(),它给出了 byte[] 的亮度值。
  4. 检查 https://github.com/jsmith613/Aruco-Marker-Tracking-Android/,我注意到它正在调用 (CvCameraViewFrame).rgba(),返回的 MatCV_8UC4 类型。我注意到调用 (Mat).get(0, 0) 会产生 double[4],例如 {1, 4, 2, 255},我推断这些对应于 RGBA。然后 Mat 传递给 (MarkerDetector).detect().
  5. 因此,我构建了一个具有相同形式和类型的 Mat 并加载了数据。
  6. Mat mat = new Mat(width, height, CvType.CV_8UC4, new Scalar(0.0, 0.0, 0.0, 255.0));
  7. (对于 x 和 y:)
  8. int lum = matrix[y * w + x] & 0xFF; mat.put(x, y, new double[]{lum, lum, lum, 255});
  9. 然后我把这个 Mat 给检测器。

有效 ,但是 for 循环很慢 - 复制所有像素大约需要一秒钟。我强烈怀疑有更快的方法 - 肯定有办法将普通字节数组传递给 Mat?仍然可以与 (MarkerDetector).detect()?

一起使用的一个

我的代码,一旦我有了 PlanarYUVLuminanceSource (source),如下所示:

Mat mat = new Mat(width, height, CvType.CV_8UC4, new Scalar(0.0, 0.0, 0.0, 255.0));
byte[] matrix = source.getMatrix();
double[] pixel = new double[]{0,0,0,255};
for (int y = 0; y < height; y++) {
  for (int x = 0; x < width; x++) {
    int luminance = matrix[y * width + x] & 0xFF;
    pixel[0] = luminance;
    pixel[1] = luminance;
    pixel[2] = luminance;
    mat.put(x, y, pixel);
  }
}
Vector<Marker> markers = new Vector<>();
mMarkerDetector.detect(mat, result, mCameraParameters, Constants.ARUCO_MARKER_SIZE, null);

好的,我成功了:

Mat mat = new Mat(height, width, CvType.CV_8UC4);
byte[] matrix = source.getMatrix();
byte[] temp = new byte[width * height * 4];
int i = 0;
mat.get(0, 0, temp);
for (int y = 0; y < height; y++) {
  for (int x = 0; x < width; x++) {
    byte luminance = matrix[y * width + x];
    temp[i++] = luminance;
    temp[i++] = luminance;
    temp[i++] = luminance;
    temp[i++] = (byte)255;
  }
}
mat.put(0, 0, temp);
Vector<Marker> markers = new Vector<>();
mMarkerDetector.detect(mat, result, mCameraParameters, Constants.ARUCO_MARKER_SIZE, null);

如果您更改 MarkerDetector 以跳过 Imgproc.cvtColor 并使用 in 而不是 grey,您可以改为:

Mat mat = new Mat(height, width, CvType.CV_8UC1);
byte[] matrix = source.getMatrix();
byte[] temp = new byte[width * height];
int i = 0;
mat.get(0, 0, temp);
System.arraycopy(matrix, 0, temp, 0, width * height);
mat.put(0, 0, temp);
Vector<Marker> markers = new Vector<>();
mMarkerDetector.detect(mat, result, mCameraParameters, Constants.ARUCO_MARKER_SIZE, null);

旁注 - 我还没有做足够的测试来确定,但似乎如果你重复使用 mMarkerDetector,检测会随着时间的推移逐渐变慢,但每次制作一个新的检测速度都相对较快。

此外,请注意,我最初交换了矩阵的维度 - 它似乎没有影响我的原始代码,但它确实影响了我输入原始数组的时间。

(请注意,所有这些代码在我的 IDE 和我的浏览器之间的传输过程中都发生了一些变化 - 不过它应该可以工作。)