我开发了一个Android项目,在其中我使用了YUV420帧并使用opencv librarires将它们转换为灰度。然后最终使用相机表面上的位图创建灰度图像。 一段时间后,应用程序停止接收帧。我甚至将帧速率降低到15.
package com.example;
import org.opencv.android.Utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
import android.graphics.Bitmap;
import android.graphics.Canvas;
//import android.graphics.drawable.BitmapDrawable;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.SurfaceHolder;
import android.hardware.Camera.Parameters;
public class Preview extends CameraDemo implements SurfaceHolder.Callback,Camera.PreviewCallback
{//Class Starts
public Camera mCamera; //Camera Object
private int PreviewSizeWidth; //Width of preview size
private int PreviewSizeHeight; //Height of Preview Size
private static final String TAG = "Preview";
public boolean drawStatus = true;
SurfaceHolder mHolder;
//Constructor to set preview size width and height
public Preview(int width, int height)
{
PreviewSizeWidth = width;
PreviewSizeHeight = height;
Log.i(TAG, "Instantiated new Preview");
}
//Override onpreviewFrame method of camera.previewcallback
@Override
public void onPreviewFrame(byte[] arg0, Camera arg1)
{
Log.i(TAG, "Frame is Received +++++");
Bitmap bmp = processFrame(arg0);
if (bmp != null) {
draw(bmp);
}
bmp.recycle();
Log.i(TAG, "Frame is Processed");
}
//Called when surface is changed
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
{
Log.i(TAG, "Surface Changed");
Parameters parameters;
parameters = mCamera.getParameters();
Size size = parameters.getPreviewSize();
PreviewSizeWidth = size.width;
PreviewSizeHeight = size.height;
parameters.setPreviewSize(PreviewSizeWidth, PreviewSizeHeight);
parameters.setPreviewFrameRate(15);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
//Called when surface is created
@Override
public void surfaceCreated(SurfaceHolder arg0) {
mHolder = arg0;
Log.i(TAG, "Surface Created");
mCamera = Camera.open();
mCamera.setPreviewCallback(this);
Log.i(TAG, "Surface Created Successfully");
}
//Called when surface is destroyed
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
//mHolder = arg0;
Log.i(TAG, "Surface Destroyed");
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
Log.i(TAG, "Surface Destroyed Exit");
}
//Process Frame Data
protected Bitmap processFrame(byte[] data)
{
Log.i(TAG, "Frame is Processing");
Mat mYUV = new Mat(PreviewSizeHeight + PreviewSizeHeight/2, PreviewSizeWidth, CvType.CV_8UC1);
mYUV.put(0, 0, data);
Mat mRgba = new Mat();
Mat mGray = new Mat();
Imgproc.cvtColor(mYUV, mRgba, Imgproc.COLOR_YUV2GRAY_NV21, 3);
Imgproc.cvtColor(mGray, mRgba, Imgproc.COLOR_GRAY2RGB, 0);
Bitmap mBitmap = Bitmap.createBitmap(PreviewSizeWidth,PreviewSizeHeight, Bitmap.Config.ARGB_8888);
try {
Utils.matToBitmap(mRgba, mBitmap);
} catch(Exception e) {
Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
mBitmap.recycle();
mBitmap = null;
}
mRgba.release();
mGray.release();
mYUV.release();
return mBitmap;
}
//For drawing bitmap
public void draw(Bitmap bmp){
Canvas canvas = mHolder.lockCanvas();
if (canvas != null) {
Log.i(TAG, "Drawing Canvas");
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()) / 2, null);
}
else{
Log.i(TAG, "Canvas is null");
}
mHolder.unlockCanvasAndPost(canvas);
}
}//CameraPreview Class ends
注意:我能够在屏幕上看到灰色图像,但在某些帧后它没有显示。
答案 0 :(得分:0)
主线程无法处理图像处理并在表面上创建位图。因此,我创建了另一个线程,它将在表面上处理和创建位图。输入帧将存储在缓冲区中。
将mCamera.setPreviewCallback(this)
更改为mCamera.setPreviewCallbackWithBuffer(this)