Die Umwandlung YUV- > RGB(Image processing)->YUV während onPreviewFrame in android?
Ich bin Aufnahme des Bildes mit SurfaceView und erste Yuv-Raw-Vorschau-Daten in public void onPreviewFrame4(byte[] data, Camera Kamera)
Habe ich Sie einige Bild-Vorverarbeitung in onPreviewFrame also muss ich konvertieren, Yuv-Vorschau-Daten, RGB-Daten als Bild-Vorverarbeitung und zurück zu Yuv-Daten.
Habe ich auch die Funktion für die Kodierung und Dekodierung von Yuv-Daten in RGB wie folgt :
public void onPreviewFrame(byte[] data, Camera camera) {
Point cameraResolution = configManager.getCameraResolution();
if (data != null) {
Log.i("DEBUG", "data Not Null");
//Preprocessing
Log.i("DEBUG", "Try For Image Processing");
Camera.Parameters mParameters = camera.getParameters();
Size mSize = mParameters.getPreviewSize();
int mWidth = mSize.width;
int mHeight = mSize.height;
int[] mIntArray = new int[mWidth * mHeight];
//Decode Yuv data to integer array
decodeYUV420SP(mIntArray, data, mWidth, mHeight);
//Converting int mIntArray to Bitmap and
//than image preprocessing
//and back to mIntArray.
//Encode intArray to Yuv data
encodeYUV420SP(data, mIntArray, mWidth, mHeight);
}
}
static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width,
int height) {
final int frameSize = width * height;
for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0)
y = 0;
if ((i & 1) == 0) {
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp++]) - 128;
}
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0)
r = 0;
else if (r > 262143)
r = 262143;
if (g < 0)
g = 0;
else if (g > 262143)
g = 262143;
if (b < 0)
b = 0;
else if (b > 262143)
b = 262143;
//rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) &
//0xff00) | ((b >> 10) & 0xff);
//rgba, divide 2^10 ( >> 10)
rgba[yp] = ((r << 14) & 0xff000000) | ((g << 6) & 0xff0000)
| ((b >> 2) | 0xff00);
}
}
}
static public void encodeYUV420SP_original(byte[] yuv420sp, int[] rgba,
int width, int height) {
final int frameSize = width * height;
int[] U, V;
U = new int[frameSize];
V = new int[frameSize];
final int uvwidth = width / 2;
int r, g, b, y, u, v;
for (int j = 0; j < height; j++) {
int index = width * j;
for (int i = 0; i < width; i++) {
r = (rgba[index] & 0xff000000) >> 24;
g = (rgba[index] & 0xff0000) >> 16;
b = (rgba[index] & 0xff00) >> 8;
//rgb to yuv
y = (66 * r + 129 * g + 25 * b + 128) >> 8 + 16;
u = (-38 * r - 74 * g + 112 * b + 128) >> 8 + 128;
v = (112 * r - 94 * g - 18 * b + 128) >> 8 + 128;
//clip y
yuv420sp[index++] = (byte) ((y < 0) ? 0 : ((y > 255) ? 255 : y));
U[index] = u;
V[index++] = v;
}
}
Das problem ist, dass die Kodierung und Dekodierung von Yuv-Daten könnten einige Fehler, weil wenn ich direkt die preprocessing-Schritt als auch codiert Yuv-Daten unterscheiden sich von den ursprünglichen Daten von PreviewCallback.
Bitte helfen Sie mir dieses Problem zu beheben. Ich habe zu eingesetzt Sie diesen code in OCR-Scannen, also muss ich implementieren diese Art der Logik.
Wenn eine andere Weise zu tun, gleiche Sache als die, bitte mir zur Verfügung stellen.
Vielen Dank im Voraus. 🙂
InformationsquelleAutor der Frage Hitesh Patel | 2012-02-17
Du musst angemeldet sein, um einen Kommentar abzugeben.
Warum nicht festlegen, dass die Kamera-Vorschau sollte bieten RGB-Bilder?
d.h. Kamera.Parameter.setPreviewFormat(ImageFormat.RGB_565);
InformationsquelleAutor der Antwort Reuben Scratton
Obwohl die Dokumentation legt nahe, dass Sie können festlegen, welches format das Bild sollten die Daten kommen von der Kamera, in der Praxis hat man oft eine Auswahl von ein: NV21, ein YUV-format. Für viele Informationen zu diesem format finden Sie unter http://www.fourcc.org/yuv.php#NV21 und für Informationen über die Theorie hinter dem umwandeln in RGB sehen http://www.fourcc.org/fccyvrgb.php. Es ist ein Bild basierend Erklärung an Extrahieren schwarz und weiß-Bild von android-Kamera NV21-format.
Einem anderen format, genannt YUV420SP, ist auch Recht weit verbreitet.
Jedoch, sobald Sie eingerichtet haben, ist Ihre onPreviewFrame routine, die mechanik, die von dem byte-array sendet es Ihnen, die nützliche Daten hat, ist etwas, hmmm, ist unklar. Aus der API, 8. die folgende Lösung ist verfügbar, um auf einem ByteStream holiding ein JPEG des Bildes (compressToJpeg ist die einzige Konvertierungs-option angeboten YuvImage):
Diese JPEG-müssen dann konvertiert werden in das format, das Sie möchten. Wenn Sie möchten, eine Bitmap:
Wenn, aus welchem Grund auch immer, Sie sind nicht in der Lage, dies zu tun, können Sie die Konvertierung manuell aus. Einige Probleme, die es zu überwinden dies zu tun:
Den Empfang der Daten in einem byte-array. Per definition sind die bytes zahlen unterzeichnet, was bedeutet, dass Sie gehen von -128 bis 127. Die Daten werden jedoch ist es eigentlich ein unsigned Byte (0 bis 255). Wenn dies nicht behandelt, das Ergebnis ist dazu verdammt, Sie zu haben, zu einigen seltsamen clipping-Effekte.
Werden die Daten in einer ganz bestimmten Reihenfolge (wie in der zuvor beschriebenen web-Seite), und jedes pixel muss extrahiert werden gezielt.
Jedes pixel muss in die richtige Stelle auf eine bitmap zu sagen. Dies erfordert auch eine eher chaotisch (aus meiner Sicht) Ansatz der Bau-Puffer mit den Daten, und dann füllen Sie eine bitmap aus.
Wenn Sie tatsächlich bekommen habe NV12 (oder 420SP), dann müssen Sie tauschen das liest sich für U und V.
Präsentiere ich eine Lösung (die scheint zu funktionieren), mit Anfragen für Korrekturen, Verbesserungen und Möglichkeiten, wie sich die ganze Sache weniger teuer zu laufen. Es erstellt ein bitmap der Größe des Vorschau-Bildes:
Daten variable kommt aus dem Aufruf onPreviewFrame
Als @Timmmm Punkte out unten, Sie könnte die Konvertierung in int, das durch die Multiplikation der Skalierung der Faktoren von 1000 (ie. 1.164 wird 1164) und dann dividng das Ergebnis durch 1000.
InformationsquelleAutor der Antwort Neil Townsend
Nach einigen tests auf dem Samsung S4 mini schnellsten code (120% schneller ist dann Neil ' s [schwimmt!] und 30% schneller als original Hitesh):
Geschwindigkeit ist vergleichbar mit YuvImage.compressToJpeg() mit ByteArrayOutputStream als Ausgang (30-50 ms für 640x480 Bild).
Ergebnis: Samsung S4 mini (2x1.7GHz) nicht komprimieren auf JPEG/konvertieren von YUV zu RGB in Echtzeit (640x480@30fps)
InformationsquelleAutor der Antwort JerzySkalski
Java-Implementierung ist 10 mal langsamer als die c-version ist, schlage ich vor, Sie GPUImage Bibliothek oder bewegen Sie einfach diesen Teil des Codes.
Gibt es eine android-version von GPUImage:
https://github.com/CyberAgent/android-gpuimage
Können Sie diese Bibliothek, wenn Sie gradle, und rufen Sie die Methode:
GPUImageNativeLibrary.YUVtoRBGA( inputArray, BREITE, HÖHE, outputArray);
Vergleiche ich die Zeit, für ein NV21 Bild, das 960x540, verwenden Sie obigen java-code, kostet es 200ms+, mit GPUImage version, nur 10ms~20ms.
InformationsquelleAutor der Antwort promenade
Korrektur der obige code-snippet
InformationsquelleAutor der Antwort HC_ZZ
Versuchen RenderScript ScriptIntrinsicYuvToRGB, die kommt mit JellyBean 4.2 (Api 17+).
https://developer.android.com/reference/android/renderscript/ScriptIntrinsicYuvToRGB.html
Auf dem Nexus 7 (2013, JellyBean 4.3) ein 1920x1080 Bild-Konvertierung (full-HD-Kamera-Vorschau) dauert etwa 7 ms.
InformationsquelleAutor der Antwort Matti81
Können Sie RenderScript -> ScriptIntrinsicYuvToRGB
InformationsquelleAutor der Antwort murgupluoglu