使用相机 API 使用渲染脚本中的 RGB 字节更新相机预览?



我已经能够从相机预览中操作字节数组并使用 renderscript 更改 yuvtorgb 中的字节。现在,我需要知道如何将该 rgb 字节渲染回相机预览。我相信无法更新相机预览。我需要在我的纹理视图之上使用某种叠加视图,然后将更新的字节数组渲染到叠加视图的表面上。我需要一些关于我应该如何去做的指导。有人可以告诉我应该怎么做吗?这就是我到目前为止尝试过的。

主要活动.java

public class MainActivity extends Activity implements TextureView.SurfaceTextureListener, Camera.PreviewCallback {
private byte[] FrameData = null;
private Camera mCamera;
private TextureView mTextureView;
Context mContext;
private Camera.Size previewSize;
private ImageView mimageView;
private SurfaceTexture mTexture;
private int[] pixels;
private int pwidth;
private int pheight;
Renderscript rv;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mimageView = new ImageView(this);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
rv = new Renderscript();
setContentView(mTextureView);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {

DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
int  mPreviewRate = Math.round((float)screenHeight / (float)screenWidth);
mCamera = Camera.open();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width*mPreviewRate, previewSize.height*mPreviewRate, Gravity.CENTER));

Camera.Parameters params = mCamera.getParameters();
if (params.getSupportedFocusModes().contains(
Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
if (params.isAutoExposureLockSupported()) {
params.setAutoExposureLock(false);
}
mCamera.setParameters(params);


pwidth = previewSize.width*mPreviewRate;
pheight = previewSize.height*mPreviewRate;
try {
mCamera.setPreviewTexture(surface);
} catch (IOException t) {
}
mCamera.setPreviewCallback(this);
mCamera.startPreview();
mTextureView.setAlpha(1.0f);
mTextureView.setRotation(90.0f);

pixels = new int[pwidth*pheight];

}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, the Camera does all the work for us
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mCamera.stopPreview();
mCamera.release();
mCamera.setPreviewCallback(null);
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Update your view here!
mCamera.setPreviewCallback(this);

}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
data = rv.convertYUV2RGB(MainActivity.this,data,pwidth,pheight);
//  sendbytearraytondkforopencvprocessing(data);




}
static {
Native.register(MainActivity.class, "native-lib");
}
public native void toGrayScale(int pixels[], int len);


}

渲染脚本.java

public byte[] convertYUV2RGB(Context c,byte[] YUVArray, int H, int W){//W: 1280, H: 720
RenderScript rs = RenderScript.create(c);
ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(YUVArray.length);
Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(W).setY(H);
Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
in.copyFrom(YUVArray);
byte[] RGBOut = new byte[W * H * 4];

yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
out.copyTo(RGBOut);

return RGBOut;
}
我相信无法

更新相机预览。

没错。

我需要在我的纹理视图之上使用某种叠加视图,然后将更新的字节数组渲染到叠加视图的表面上。

你可以在OpenCV中看到类似的方法。他们的Android演示显示RGB预览。他们不使用渲染脚本,但这并不重要。无论如何,帧速率(取决于CPU功率和相机分辨率(通常不够流畅。

为了获得更好的性能,您可以使用纹理视图,或者更准确地说,通过在 EGL 纹理上直接设置像素 (glTexSubImage2D( 来使用 GPU。请参阅示例。

但是如果你这样做,你实际上浪费了大量的时间在CPU和GPU之间传递数据:一次使用渲染脚本,然后再次设置纹理。相反,您可以使用 OpenGL 直接设置 YUV 像素,并使用着色器将它们转换为 RGB 进行显示。

最新更新