Dai*_*nis 3 java camera android bitmap yuv
我正在尝试从相机预览中捕获图像并对其进行绘制.问题是,我只有大约3-4 fps的绘图,并且一半的帧处理时间是从摄像机预览接收和解码NV21图像并转换为位图.我有一个代码来执行此任务,我在另一个堆栈问题上找到了该代码.它似乎并不快,但我不知道如何优化它.三星Note 3需要大约100-150毫秒,图像尺寸为1920x1080.如何让它更快地运作?
代码:
public Bitmap curFrameImage(byte[] data, Camera camera)
{
Camera.Parameters parameters = camera.getParameters();
int imageFormat = parameters.getPreviewFormat();
if (imageFormat == ImageFormat.NV21)
{
YuvImage img = new YuvImage(data, ImageFormat.NV21, prevSizeW, prevSizeH, null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
img.compressToJpeg(new android.graphics.Rect(0, 0, img.getWidth(), img.getHeight()), 50, out);
byte[] imageBytes = out.toByteArray();
return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
}
else
{
Log.i(TAG, "Preview image not NV21");
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
图像的最终格式必须是位图,因此我可以对其进行处理.我试图将Camera.Parameters.setPreviewFormat设置为RGB_565,但无法将相机参数分配给相机,我还读到NV21是唯一可用的格式.我不确定,是否有可能在这些格式变化中找到解决方案.
先感谢您.
感谢Alex Cohn,帮助我更快地完成转换.我实现了您建议的方法(RenderScript内在函数).此代码由RenderScript内在函数构成,将YUV图像转换为位图的速度提高约5倍.以前的代码花了100-150毫秒.在三星Note 3上,这需要15-30左右.如果有人需要执行相同的任务,这里是代码:
这些将被使用:
private RenderScript rs;
private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
private Type.Builder yuvType, rgbaType;
private Allocation in, out;
Run Code Online (Sandbox Code Playgroud)
在创建函数我初始化..:
rs = RenderScript.create(this);
yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
Run Code Online (Sandbox Code Playgroud)
整个onPreviewFrame看起来像这样(这里我接收并转换图像):
if (yuvType == null)
{
yuvType = new Type.Builder(rs, Element.U8(rs)).setX(dataLength);
in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(prevSizeW).setY(prevSizeH);
out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
}
in.copyFrom(data);
yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
Bitmap bmpout = Bitmap.createBitmap(prevSizeW, prevSizeH, Bitmap.Config.ARGB_8888);
out.copyTo(bmpout);
Run Code Online (Sandbox Code Playgroud)
您可以获得更高的速度(使用JellyBean 4.3,API18或更高版本):相机预览模式必须为NV21!
在“ onPreviewFrame()”上仅执行:
aIn.copyFrom(data);
yuvToRgbIntrinsic.forEach(aOut);
aOut.copyTo(bmpout); // and of course, show the bitmap or whatever
Run Code Online (Sandbox Code Playgroud)
不要在此处创建任何对象。
在开始相机预览之前,所有其他内容(创建rs,yuvToRgbIntrinsic,分配,位图)都在onCreate()方法中进行。
rs = RenderScript.create(this);
yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
// you don´t need Type.Builder objects , with cameraPreviewWidth and cameraPreviewHeight do:
int yuvDatalength = cameraPreviewWidth*cameraPreviewHeight*3/2; // this is 12 bit per pixel
aIn = Allocation.createSized(rs, Element.U8(rs), yuvDatalength);
// of course you will need the Bitmap
bmpout = Bitmap.createBitmap(cameraPreviewWidth, cameraPreviewHeight, Bitmap.Config.ARGB_8888);
// create output allocation from bitmap
aOut = Allocation.createFromBitmap(rs,bmpout); // this simple !
// set the script´s in-allocation, this has to be done only once
yuvToRgbIntrinsic.setInput(aIn);
Run Code Online (Sandbox Code Playgroud)
在Nexus 7(2013,JellyBean 4.3)上,全高清(1920x1080)摄像机预览转换大约需要0.007秒(是,7毫秒)。