Установить ARCore Sceneview на другой элемент экрана - PullRequest
0 голосов
/ 04 декабря 2018

Я пытаюсь отобразить один arFragment дважды на моем экране, просто используя подачу одного фрагмента и устанавливая другой элемент экрана на то же самое, но я не могу понять, какой элемент взять.

Я знаю, что я получаю текущее изображение с камеры, вызывая

ArFragment arFragment = (ArFragment) getSupportFragmentManager()
                           .findFragmentById(R.id.arFragment);
Image image = arFragment.getArSceneView().getArFrame().acquireCameraImage();

Но я не знаю, как взять другой экранный объект и установить вид на канал, arFragment дает мне.Например:

TextureView secondView = (TextureView) findViewById(R.id.texture);
secondView.setSurfaceTexture((SurfaceTexture) image);

приводит к ошибке необратимых типов.

Я не могу использовать другой arFragment, потому что для него уже назначена другая камера (та, которая дает черный экран и "камера уже используется "ошибка, очевидно).Я не нашел метод

arFrame.assignCamera();

, который не имеет значения, поскольку камера, используемая Фрагментом, является только объектом, а не реальной вещью.Но я не могу понять, где аппаратное обеспечение привязано к фрагменту.И я не могу ни читать, ни писать там, если я правильно помню.

Я мог бы преобразовать канал в растровое изображение и, возможно, поместить его в imageView, но я немного боюсь делать это 60 раз в секунду.Должно быть простое решение, верно? ...

Не может быть так сложно дважды отобразить представление -.-

1 Ответ

0 голосов
/ 06 декабря 2018

Хорошо, понял.Это немного волшебно с преобразованием в bmp, но думаю, что на самом деле прямого пути нет.

Итак, я инициализировал байтовый буфер, проанализировал YUV-компоненты android.media.image, преобразовал их в Jpeg, затем изменил его.в растровое изображение, поверните его на 90 °, чтобы соответствовать исходному изображению.

// get the arFragment
arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.arFragment);
ArSceneView arSceneView = arFragment.getArSceneView();

// set up a Listener to trigger on every frame
arSceneView.getScene().addOnUpdateListener(frameTime -> 
{
  try 
  {
   frame = arSceneView.getArFrame();
   androidMediaImage = frame.acquireCameraImage();
   int imageWidth = androidMediaImage.getWidth();
   int imageHeight = androidMediaImage.getHeight();

   // select the target Container to display the image in
   ImageView secondView = (ImageView) findViewById(R.id.imageView3);
   byte[] nv21;

   // an Android.Media.Image is a YUV-Image which is made out of 3 planes
   ByteBuffer yBuffer = androidMediaImage.getPlanes()[0].getBuffer();
   ByteBuffer uBuffer = androidMediaImage.getPlanes()[1].getBuffer();
   ByteBuffer vBuffer = androidMediaImage.getPlanes()[2].getBuffer();

   // set up a Bytearray with the size of all the planes
   int ySize = yBuffer.remaining();
   int uSize = uBuffer.remaining();
   int vSize = vBuffer.remaining();

   nv21 = new byte[ySize + uSize + vSize];

   // Fill in the array. This code is directly taken from https://www.programcreek.com 
   //where it was pointed out that U and V have to be swapped
   yBuffer.get(nv21, 0 , ySize);
   vBuffer.get(nv21, ySize, vSize);
   vBuffer.get(nv21, ySize + vSize, uSize);

   // combine the three layers to one nv21 image
   YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, imageWidth, imageHeight, null);
   // Open a Bytestream to feed the compressor
   ByteArrayOutputStream out = new ByteArrayOutputStream();
   // compress the yuv image to Jpeg. This is important, because the BitmapFactory can't read a 
   // yuv-coded image directly (belief me I tried -.-)
   yuvImage.compressToJpeg(new Rect(0, 0, imageWidth, imageHeight), 50, out);
   // now write down the bytes of the image into an array
   byte[] imageBytes = out.toByteArray();
   // and build the bitmap using the Factory
   Bitmap bitmapImage = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);

   // use a Matrix for the rotation
   Matrix rotationMatrix = new Matrix();
   // the thing is basically a bunch of numbers which then can be used to compute the new location of each pixel
   rotationMatrix.postRotate(90);
   // the rotatedImage will be our target image
   Bitmap rotatedImage = Bitmap.createBitmap(bitmapImage, 0,0, bitmapImage.getWidth(), bitmapImage.getHeight(), rotationMatrix, true);

   // it's so easy!!!!
   secondView.setImageBitmap(rotatedImage);
  } catch (NotYetAviableException e) 
   {
     e.printStackTrace();
   }
});

Вы, очевидно, можете исправить меня, если я все неправильно понял, и есть более простое решение для этого.Но это работает по крайней мере, поэтому я счастлив <3 </p>

...