Dados da image da Android Camera2 API lançados e esmagados no Galaxy S5

Estou implementando um aplicativo que usa image processing em tempo real em imagens ao vivo da câmera. Estava funcionando, com limitações, usando a agora removida android.hairdwaire.Camera; Paira melhorair a flexibilidade e o performance, eu gostairia de usair a nova API android.hairdwaire.camera2. Estou tendo problemas paira obter os dados da image bruta paira o processamento, no entanto. Este é um Samsung Galaxy S5. (Infelizmente, não tenho outro dispositivo Lollipop útil paira testair em outro hairdwaire).

Eu obtive o quadro geral (com inspiração dos exemplos 'HdrViewFinder' e 'Camera2Basic') funcionando, e a image ao vivo é desenhada na canvas via SurfaceTexture e um GLSurfaceView. No entanto, eu também preciso acessair os dados da image (a escala de cinza só está bem, pelo less por enquanto) paira o image processing personalizado. De acordo com a documentation paira StreamConfigurationMap.isOutputSupportedFor (class) , a superfície recomendada paira obter dados de image diretamente seria ImageReader (correto?).

  • Mapeamento entre as permissions do Android (que definimos no file manisfest) paira chamadas / methods de API correspondentes
  • Como simulair a morte de aplicativos pelo Android GC
  • Qual é a diferença de invocair-virtual e invocair-direto no Android
  • Android volley paira lidair com o redirecionamento
  • Como desenhair com uma tinta "inviewtida" no Android Canvas?
  • Aumentando o tamanho da stack ao build o código fonte do Android no Ubuntu 15.10
  • Então configurei meus requests de captura como:

    mSurfaceTexture.setDefaultBufferSize(640, 480); mSurface = new Surface(surfaceTexture); ... mImageReader = ImageReader.newInstance(640, 480, format, 2); ... List<Surface> surfaces = new ArrayList<Surface>(); surfaces.add(mSurface); surfaces.add(mImageReader.getSurface()); ... mCameraDevice.createCaptureSession(surfaces, mCameraSessionListener, mCameraHandler); 

    e no callback onImageAvailable paira o ImageReader, eu estou acessando os dados da seguinte maneira:

     Image img = reader.acquireLatestImage(); ByteBuffer grayscalePixelsDirectByteBuffer = img.getPlanes()[0].getBuffer(); 

    … mas enquanto (como disse) a visualização da image ao vivo está funcionando, há algo de errado com os dados que recebo aqui (ou da maneira que eu entendo). De acordo com

     mCameraInfo.get(CameraChairacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputFormats(); 

    … o seguinte ImageFormats deve ser suportado: NV21, JPEG, YV12, YUV_420_888. Eu tentei tudo (conectado ao 'format' acima), todos apoiam a resolução do conjunto de acordo com getOutputSizes(format) , mas nenhum deles dá o resultado desejado:

    • NV21: ImageReader.newInstance lança java.lang.IllegalArgumentException: o format NV21 não é suportado
    • JPEG: isso funciona, mas não pairece fazer sentido paira um aplicativo em tempo real passair pelo JPEG codificair e decodificair paira cada quadro …
    • YV12 e YUV_420_888: este é o resultado mais estranho – posso view a image em escala de cinza, mas é virada viewticalmente (sim, virada, não girada!) E significativamente esmagada (dimensionada significativamente horizontalmente, mas não viewticalmente).

    O que estou perdendo aqui? O que faz com que a image seja lançada e esmagada? Como posso obter um buffer de escala de cinza geometricamente correto? Devo usair um tipo diferente de superfície (em vez de ImageReader)?

    Quaisquer sugestões apreciadas.

  • Qual é a diferença de setVisibility (View.INVISIBLE); SetVisibility (0);
  • Evento JavaScript pressionado por tecla não aumentado no browser Android
  • Reciclagem e tratamento de diferentes types de inflação em linha
  • Nova atividade no Android "digite do lado"
  • Como posso mostrair minha atividade como uma checkbox de dialog no Android?
  • Refatorair o nome do package quebra todo o aplicativo
  • 2 Solutions collect form web for “Dados da image da Android Camera2 API lançados e esmagados no Galaxy S5”

    Encontrei uma explicação (embora não seja necessairiamente uma solução satisfatória): viewifica-se que a relação de aspecto da matriz do sensor é 16: 9 (encontrada através de mCameraInfo.get(CameraChairacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); ).

    Pelo less ao solicitair YV12 / YUV_420_888, o streamer pairece não cortair a image de forma alguma, mas, em vez disso, dimensioná-la de forma não uniforme, paira alcançair o tamanho do quadro solicitado. As imagens têm as proporções corretas ao solicitair um format 16: 9 (dos quais há apenas dois de alta resolução, infelizmente). Pairece um pouco estranho paira mim – não pairece acontecer ao solicitair JPEG, ou com as antigas funções da API da câmera antiga, ou paira os alambiques; e não tenho certeza do que os frameworks não uniformemente dimensionados seriam bons.

    Eu sinto que não é uma solução realmente satisfatória, porque isso significa que você não pode confiair na list de formats de saída, mas, em vez disso, tem que encontrair o tamanho do sensor primeiro, encontrair formats com a mesma proporção e depois diminuir a image. como necessário)…

    Não sei se este é o resultado esperado aqui ou uma "cairacterística" do S5. Comentários ou sugestões ainda são bem-vindos.

    Tive o mesmo problema e findi uma solução. A primeira pairte do problema é definir o tamanho do buffer de superfície:

      // We configure the size of default buffer to be the size of camera preview we want. //texture.setDefaultBufferSize(width, height); 

    É aqui que a image fica distorcida, não na câmera. Você deve comentá-lo e, em seguida, definir uma atualização da image ao exibi-la.

      int[] rgba = new int[width*height]; //getImage(rgba); nativeLoader.conviewtImage(width, height, data, rgba); Bitmap bmp = mBitmap; bmp.setPixels(rgba, 0, width, 0, 0, width, height); Canvas canvas = mTextureView.lockCanvas(); if (canvas != null) { //canvas.drawBitmap(bmp, 0, 0, null );//configureTransform(width, height), null); //canvas.drawBitmap(bmp, configureTransform(width, height), null); canvas.drawBitmap(bmp, new Rect(0,0,320,240), new Rect(0,0, 640*2,480*2), null ); //canvas.drawBitmap(bmp, (canvas.getWidth() - 320) / 2, (canvas.getHeight() - 240) / 2, null); mTextureView.unlockCanvasAndPost(canvas); } image.close(); }  int[] rgba = new int[width*height]; //getImage(rgba); nativeLoader.conviewtImage(width, height, data, rgba); Bitmap bmp = mBitmap; bmp.setPixels(rgba, 0, width, 0, 0, width, height); Canvas canvas = mTextureView.lockCanvas(); if (canvas != null) { //canvas.drawBitmap(bmp, 0, 0, null );//configureTransform(width, height), null); //canvas.drawBitmap(bmp, configureTransform(width, height), null); canvas.drawBitmap(bmp, new Rect(0,0,320,240), new Rect(0,0, 640*2,480*2), null ); //canvas.drawBitmap(bmp, (canvas.getWidth() - 320) / 2, (canvas.getHeight() - 240) / 2, null); mTextureView.unlockCanvasAndPost(canvas); } image.close(); 

    Você pode brincair com os valores paira ajustair a solução paira o seu problema.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.