【问题标题】:Java OpenCV Aruco MatJava OpenCV Aruco Mat
【发布时间】:2018-05-10 21:21:05
【问题描述】:

我正在尝试将 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);

【问题讨论】:

    标签: android opencv optimization yuv


    【解决方案1】:

    好的,我搞定了:

    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 和浏览器之间的传输过程中都发生了一些变化——不过它应该可以工作。)

    【讨论】:

      猜你喜欢
      • 2016-10-05
      • 1970-01-01
      • 2022-10-12
      • 2018-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-17
      • 2017-11-29
      相关资源
      最近更新 更多