2015-11-05 3 views
8

Я пытаюсь преобразовать изображение из YUV_420_888 в rgb, и у меня есть некоторые проблемы с выходным изображением. В ImageReader я получаю изображение в формате YUV_420_888 (используя камеру 2 api для получения этого предварительного просмотра).camera2 api конвертировать yuv420 в rgb green out

imageReader = ImageReader.newInstance(1920,1080,ImageFormat.YUV_420_888,10); 

В Android SDK для написания класса YuvImage, что YuvImage используя только NV21, YUY2.

как мы можем видеть разницу между N21 и yuv420 не большой и я пытаюсь преобразовать данные в N21

YUV420: enter image description here

и N21: enter image description here

в onImageAvailable Я получаю отдельно каждый Самолеты и помещаю их в правильное место (как на изображении)

ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 

ByteBuffer bufferY = image.getPlanes()[0].getBuffer(); 
byte[] data0 = new byte[bufferY.remaining()]; 
bufferY.get(data0); 

ByteBuffer bufferU = image.getPlanes()[1].getBuffer(); 
byte[] data1 = new byte[bufferU.remaining()]; 
bufferU.get(data1); 

ByteBuffer bufferV = image.getPlanes()[2].getBuffer(); 
byte[] data2 = new byte[bufferV.remaining()]; 
bufferV.get(data2); 
... 
outputStream.write(data0); 
for (int i=0;i<bufferV.remaining();i++) { 
    outputStream.write(data1[i]); 
    outputStream.write(data2[i]); 
} 

после создания YuvImage, преобразовать в растровый, просматривать и сохранять

final YuvImage yuvImage = new YuvImage(outputStream.toByteArray(), ImageFormat.NV21, 1920,1080, null); 
ByteArrayOutputStream outBitmap = new ByteArrayOutputStream(); 

yuvImage.compressToJpeg(new Rect(0, 0,1920, 1080), 95, outBitmap); 

byte[] imageBytes = outBitmap.toByteArray(); 

final Bitmap imageBitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); 
mImageView.setImageBitmap(imageBitmap); 
... 
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 95, out); 

но мое сохраненное изображение зеленый и розовый: capture image capture image

что же я скучаю ??

+2

мелочью: диаграмма для NV21 на самом деле не так и изображает кодирование NV12. NV21 - это то же самое, за исключением того, что U и V заменяются, то есть VUVUVUVUV вместо UVUVUVUVUV. – samgak

ответ

2

bufferV.get(data2) увеличивает положение ByteBuffer. Вот почему петля for (int i=0;i<bufferV.remaining();i++) производит 0 итераций. Вы можете легко переписать его как

for (int i=0; i<data1.length; i++) { 
    outputStream.write(data1[i]); 
    outputStream.write(data2[i]); 
} 
+0

я меняю это ... но то же самое. Я проверил, что внутри массива ** data1 **, ** data2 ** и они почти 0. Длина массива 518400 и от этой длины 517440 равна 0. Может быть, можно использовать только первые 960? –

+0

Это может быть неисправная реализация API камеры2 на вашем устройстве. –

3

Есть две основные проблемы на вашей конверсии попытка:

  1. Мы не можем предположить, что плоскости U и V являются изолированными, они могут содержать чередующиеся данные (например, U-PLANE = {U1, V1, U2, V2, ...}). На самом деле это может быть даже чередование стиля NV21. Ключ здесь находится на плоскости row stride и pixel stride, а также проверьте, что мы можем принять по поводу YUV_420_888 format.
  2. Тот факт, что вы отметили, что большинство данных U-V-плоскостей являются нулями, указывает, что вы испытываете Android bug on the generation of images in YUV_420_888. Это означает, что даже если вы получите правильное преобразование, изображение все равно будет выглядеть зеленым, если на вас повлияет ошибка, которая была зафиксирована только на Android 5.1.1 и выше, поэтому стоит проверить, какую версию вы используете, кроме того исправление кода.
+0

спасибо за ссылку с ошибкой android, я проверю свою версию и у меня 5.0.1 тоже. поэтому я попробую обновить свой андроид и увижу, какое изменение –

3

Я реализовал YUV_420 логику (точно так, как показано на рисунке выше) в Renderscript см полный код здесь:

Conversion YUV_420 _888 to Bitmap, complete code

Он производит совершенные bimaps для API 22, но для API 21 он показывает «зеленую идиллию». Из этого я могу подтвердить, результаты, которые вы нашли. Как уже упоминалось выше, Silvaren, по-видимому, является ошибкой Android в API 21. Глядя на мой код rs, ясно, что если информация U и V отсутствует (т.е. нуль), компонент ARGB G (reen) становится огромным во время преобразование.

Я вижу похожие зеленые картинки на моей Галактике S5 (еще API 21) - здесь даже вверх ногами ;-). Я подозреваю, что большинство устройств в API 21 в настоящее время еще не используют Camera2 для своих приложений для устройств. Существует бесплатное приложение под названием «Совместимость с ручной камерой», которое позволяет проверить это. Из этого я вижу, что на самом деле S5/API21 все еще не использует Camera2 ... к счастью, нет ...

2

У меня есть изображение ImageFormat.YUV_420_888 и было успешно сохранить файл jpeg и можно было корректно просмотреть его на окнах ,
Я делюсь здесь:

private final Image mImage; 
private final File mFile; 
private final int mImageFormat; 


ByteArrayOutputStream outputbytes = new ByteArrayOutputStream(); 

ByteBuffer bufferY = mImage.getPlanes()[0].getBuffer(); 
byte[] data0 = new byte[bufferY.remaining()]; 
bufferY.get(data0); 

ByteBuffer bufferU = mImage.getPlanes()[1].getBuffer(); 
byte[] data1 = new byte[bufferU.remaining()]; 
bufferU.get(data1); 

ByteBuffer bufferV = mImage.getPlanes()[2].getBuffer(); 
byte[] data2 = new byte[bufferV.remaining()]; 
bufferV.get(data2); 

try 
{ 
    outputbytes.write(data0); 
    outputbytes.write(data2); 
    outputbytes.write(data1); 


    final YuvImage yuvImage = new YuvImage(outputbytes.toByteArray(), ImageFormat.NV21, mImage.getWidth(),mImage.getHeight(), null); 
    ByteArrayOutputStream outBitmap = new ByteArrayOutputStream(); 

    yuvImage.compressToJpeg(new Rect(0, 0,mImage.getWidth(), mImage.getHeight()), 95, outBitmap); 


    FileOutputStream outputfile = null; 
    outputfile = new FileOutputStream(mFile); 
    outputfile.write(outBitmap.toByteArray()); 
} 
catch (IOException e) 
{ 
    e.printStackTrace(); 
} 
finally 
{ 
    mImage.close(); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^