Grüne Bilder bei einer JPEG-Kodierung von YUV_420_888 mit der neuen Android-Kamera2-api
Ich bin versucht, die neue Kamera-api. Die burst-Erfassung im Begriff war zu langsam, so dass ich die YUV_420_888-format in den ImageReader und eine JPEG-enconding später, als wurde vorgeschlagen, in den folgenden post:
Android-Kamera2-capture-burst ist zu langsam
Das problem ist, dass ich immer grüne Bilder, wenn ich versuchen zu codieren JPEG aus YUV_420_888 mit RenderScript wie folgt:
RenderScript rs = RenderScript.create(mContext);
ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.RGBA_8888(rs));
Type.Builder yuvType = new Type.Builder(rs, Element.YUV(rs)).setX(width).setY(height).setYuvFormat(ImageFormat.YUV_420_888);
Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
in.copyFrom(data);
yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
Bitmap bmpout = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
out.copyTo(bmpout);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmpout.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] jpegBytes = baos.toByteArray();
Daten-variable (die YUV_420_888 Daten) ermittelt sich aus:
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
Was mache ich falsch in der JPEG-Kodierung zu erhalten, werden die Bilder nur in grün?
Vielen Dank im Voraus
Bearbeitet werden: Dies ist ein Beispiel für die Bilder in grün, die ich erhalten:
https://drive.google.com/file/d/0B1yCC7QDeEjdaXF2dVp6NWV6eWs/view?usp=sharing
- FWIW, ein YUV-Wert 0,0,0 ist eine mittlere grüne Farbe. Also, wenn Ihr Bild ist ganz grün, meine Vermutung ist, das Sie konvertieren einen Puffer voll von Nullen, anstatt einen Puffer voll von YUV-pixel-Daten.
- Ich habe bearbeitet die Frage mit einem Beispiel, die Bilder, die ich abrufen. Sie sind sich nicht ganz grün, es scheint grün-Skala. Ich denke, das ist, weil ich die Daten nur aus der ersten Ebene der drei, YUV-format haben. Ich Suche einen Weg, um die Informationen aus den drei Ebenen und es passieren die RenderScript, aber ich war nicht in der Lage, um den kleinen code, den ich gefunden habe, arbeiten.
- HI, hast du es geschafft dieses problem zu lösen?
- Ich habe versucht die codes und die gespeicherte png-Bild ist grün. Es scheint, dass ScriptIntrinsicYuvToRGB nicht verwandeln YUV_420_888 in bitmap. Haben Sie einen anderen Weg finden, es zu erreichen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
So gibt es mehrere Ebenen von Antworten auf diese Frage.
Ersten, ich glaube nicht, dass es einen direkten Weg, um kopieren Sie ein Bild von YUV_420_888 Daten in ein RS-Zuweisung, selbst wenn die Zuordnung von format YUV_420_888.
Also, wenn Sie Sie nicht verwenden das Bild für etwas anderes, als diese JPEG-encode Schritt, dann können Sie einfach eine Zuweisung als Ausgang für die Kamera direkt mithilfe Zuordnung#getSurface und Zuordnung#ioReceive. Dann können Sie führen Sie Ihre YUV->RGB-Umwandlung und Auslesen der bitmap.
Beachten Sie jedoch, dass JPEG-Dateien unter der Haube, eigentlich speichern YUV-Daten, so dass, wenn Sie gehen, um das komprimieren des JPEG -, Bitmap noch ein RGB->YUV-Konvertierung, wie es die Datei speichert. Für maximale Effizienz, dann wollen Sie füttern die YUV-Daten direkt in ein JPEG-encoder, die es akzeptieren können, und vermeiden Sie die zusätzliche Umwandlung Schritte völlig. Leider ist es nicht möglich, über die öffentlichen APIs, so müssten Sie die drop-down-to-JNI code und geben Sie Ihre eigene Kopie von libjpeg oder eine gleichwertige JPEG encoding-Bibliothek.
Wenn Sie nicht brauchen, um zu speichern Sie JPEG-Dateien furchtbar schnell, Sie können swizzle die YUV_420_888 Daten in ein NV21 byte [], und verwenden Sie dann YuvImage, aber Sie müssen die Aufmerksamkeit auf die pixel und Zeile Fortschritte Ihrer YUV_420_888 Daten und ordnen Sie Sie richtig zu NV21 - YUV_420_888 ist flexibel und darstellen können mehrere verschiedene Arten von Speicher-layouts (einschließlich NV21) und unterscheiden sich auf den verschiedenen Geräten. Also, wenn Sie das layout ändern, um NV21, ist es entscheidend, um sicherzustellen, dass Sie tun, richtig zuordnen.
USAGE_IO_INPUT
das funktionieren könnte. Außerdem, ich werde nicht überrascht sein, wenn unter der Haube dieses format wird ignoriert, und HAL stellt die tatsächliche oder NV21 YV12 statt, siehe z.B. rsallocation.cHabe ich es geschafft, diese zu arbeiten, die Antwort panonski ist nicht ganz richtig, und ein großes Problem ist, dass diese
YUV_420_888
format deckt viele verschiedene Speicher-layouts, wo derNV21
- format ist sehr spezifisch (ich weiß nicht, warum das Standard-format wurde geändert, es macht für mich keinen Sinn)Beachten Sie, dass diese Methode ziemlich langsam für ein paar Gründe.
Weil
NV21
vernetzt die chroma-Kanäle, undYUV_420_888
enthält Formate, die nicht-Zeilensprung-chroma-Kanälen, die einzige zuverlässige Möglichkeit (die ich kenne) ist, um einen byte-für-byte-Kopie. Ich bin daran interessiert zu wissen, ob es einen trick um diesen Prozess zu beschleunigen, ich vermute, es ist einer. Ich biete eine Graustufen-option nur, denn das Teil ist sehr schnell Zeile für Zeile kopieren.Wenn packte frames von der Kamera, die bytes werden als geschützt gekennzeichnet werden, die mittels direkter Zugang nicht möglich ist und Sie müssen kopiert werden, direkt manipuliert werden.
Erscheint das Bild gespeichert werden in umgekehrter byte-Reihenfolge, also nach der Umwandlung des letzten array muss rückgängig gemacht werden. Dies könnte nur sein, meine Kamera und ich vermute, es ist ein weiterer trick, um die hier gefunden werden können, dass diese Fahrt eine Menge.
Egal, hier ist der code:
Wenn Verstand ich Ihre Beschreibung richtig ich sehe mindestens zwei Probleme in deinem code:
Es scheint, Sie sind nur vorbei an der Y-Teil des Bildes, um die YUV->RGB conversion-code, denn es sieht aus wie Sie nur mit dem ersten Flugzeug in
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
, ignorieren Sie die U-und V-Ebenen.Ich bin nicht vertraut mit diesen Renderscript Typen noch nicht, aber es sieht aus wie das Element.RGBA_8888 und Bitmap.Config.ARGB_8888 beziehen sich auf leicht unterschiedliche reihungen von bytes, so müssen Sie möglicherweise einige der Neuordnung der Arbeit.
Beide Probleme könnte die Ursache für die grüne Farbe des entstehenden Bildes.
Haben Sie verwenden, um RenderScript?
Wenn nicht, könnten Sie verwandeln das Bild von YUV auf N21 und dann von N21 zu JPEG ohne aufwändige Strukturen.
Zuerst nehmen Sie die 0 und die 2 Ebene zu bekommen N21:
Dann können Sie YuvImage integrierte Methode zur Komprimierung von JPEG. Die
w
und dieh
Parameter sind die Breite und die Höhe des Bildes Datei.Dies ist eine Antwort/Frage.
Auf einigen ähnlichen post, ist es empfehlenswert, verwenden Sie dieses Skript :
https://github.com/pinguo-yuyidong/Camera2/blob/master/camera2/src/main/rs/yuv2rgb.rs
Aber ich weiß nicht, wie es zu benutzen. Ratschläge sind willkommen.
Haben die oben genannten Konvertierung funktioniert hat? da versuchte ich es mit renderscript durch kopieren die erste und Letzte Flugzeug, und ich, noch erhielt einen grün gefilterten Bild, wie die von oben.