Java OpenCV Aruco Mat - PullRequest
       11

Java OpenCV Aruco Mat

0 голосов
/ 11 мая 2018

Я пытаюсь передать изображение предварительного просмотра камеры Android в OpenCV для обнаружения кодов Aruco. Исходя из предыдущей работы, текущий поток выглядит следующим образом:

  1. У меня есть YUV Image.Plane.
  2. Я кормлю его в ZXing PlanarYUVLuminanceSource.
  3. На этом я называю getMatrix(), что дает мне byte[] значений яркости.
  4. Проверка https://github.com/jsmith613/Aruco-Marker-Tracking-Android/, Я заметил, что он вызывает (CvCameraViewFrame).rgba(), а возвращаемый Mat имеет тип CV_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);

1 Ответ

0 голосов
/ 11 мая 2018

Хорошо, у меня все получилось:

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 и моим браузером - хотя он ДОЛЖЕН работать.)

...