android Camera2

举报
风吹稻花香 发表于 2021/06/05 01:13:33 2021/06/05
【摘要】   控件: import android.view.TextureView; 这个是代码: https://github.com/plumcot/Camera2Demo/blob/master/src/com/example/camera2demo/Camera2Demo.java   获取图片数据不对,应该是:   privat...

 

控件:

import android.view.TextureView;

这个是代码:

https://github.com/plumcot/Camera2Demo/blob/master/src/com/example/camera2demo/Camera2Demo.java

 

获取图片数据不对,应该是:

 


      private void setupImageReader() {
      //前三个参数分别是需要的尺寸和格式,最后一个参数代表每次最多获取几帧数据,本例的2代表ImageReader中最多可以获取两帧图像流
       mImageReader = ImageReader.newInstance(mPreviewSize.getWidth(), mPreviewSize.getHeight(),
       ImageFormat.JPEG, 2);
      //监听ImageReader的事件,当有图像流数据可用时会回调onImageAvailable方法,它的参数就是预览帧数据,可以对这帧数据进行处理
       mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
      @Override
      public void onImageAvailable(ImageReader reader) {
       Image image = reader.acquireLatestImage();
      //我们可以将这帧数据转成字节数组,类似于Camera1的PreviewCallback回调的预览帧数据
       ByteBuffer buffer = image.getPlanes()[0].getBuffer();
      byte[] data = new byte[buffer.remaining()];
       buffer.get(data);
       image.close();
       }
       }, null);
      }
  
 

 


      package com.mtcnn_as;
      import java.nio.ByteBuffer;
      import java.util.Arrays;
      import android.Manifest;
      import android.app.Activity;
      import android.content.Context;
      import android.content.pm.PackageManager;
      import android.graphics.Bitmap;
      import android.graphics.BitmapFactory;
      import android.graphics.ImageFormat;
      import android.graphics.Matrix;
      import android.graphics.SurfaceTexture;
      import android.hardware.camera2.CameraAccessException;
      import android.hardware.camera2.CameraCaptureSession;
      import android.hardware.camera2.CameraCharacteristics;
      import android.hardware.camera2.CameraDevice;
      import android.hardware.camera2.CameraManager;
      import android.hardware.camera2.CaptureRequest;
      import android.hardware.camera2.params.StreamConfigurationMap;
      import android.media.Image;
      import android.media.ImageReader;
      import android.os.Bundle;
      import android.os.Handler;
      import android.os.HandlerThread;
      import android.support.v4.app.ActivityCompat;
      import android.support.v4.content.ContextCompat;
      import android.util.Log;
      import android.util.Size;
      import android.view.Surface;
      import android.view.TextureView;
      import static com.mtcnn_as.ImageUtils.saveBitmap;
      public class Camera2Demo extends Activity implements
     		TextureView.SurfaceTextureListener {
     	private CameraDevice mCamera;
     	private String mCameraID = "1";
     	private TextureView mPreviewView;
     	private Size mPreviewSize;
     	private CaptureRequest.Builder mPreviewBuilder;
     	private ImageReader mImageReader;
     	private Handler mHandler;
     	private HandlerThread mThreadHandler;
     	// 这里定义的是ImageReader回调的图片的大小
     	private int mImageWidth = 1920;
     	private int mImageHeight = 1080;
     	@Override
     	public void onCreate(Bundle savedInstanceState) {
     		super.onCreate(savedInstanceState);
      		setContentView(R.layout.activity_texture);
      		initView();
      		initLooper();
      	}
     	// 很多过程都变成了异步的了,所以这里需要一个子线程的looper
     	private void initLooper() {
      		mThreadHandler = new HandlerThread("CAMERA2");
      		mThreadHandler.start();
      		mHandler = new Handler(mThreadHandler.getLooper());
      	}
     	// 可以通过TextureView或者SurfaceView
     	private void initView() {
      		mPreviewView = (TextureView) findViewById(R.id.textureView);
      		mPreviewView.setSurfaceTextureListener(this);
      	}
     	@Override
     	public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
      int height) {
     		try {
     			// 获得所有摄像头的管理者CameraManager
      			CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
     			// 获得某个摄像头的特征,支持的参数
      			CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(mCameraID);
     			// 支持的STREAM CONFIGURATION
      			StreamConfigurationMap map = characteristics
       .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
     			// 摄像头支持的预览Size数组
      			mPreviewSize = map.getOutputSizes(SurfaceTexture.class)[0];
     			if (ContextCompat.checkSelfPermission(Camera2Demo.this,
       Manifest.permission.CAMERA)
       != PackageManager.PERMISSION_GRANTED ||
       ContextCompat.checkSelfPermission(Camera2Demo.this,
       Manifest.permission.WRITE_EXTERNAL_STORAGE)
       != PackageManager.PERMISSION_GRANTED) {
       ActivityCompat.requestPermissions(Camera2Demo.this,
      new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
      			}
     			// 打开相机
     			if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
      // TODO: Consider calling
      // ActivityCompat#requestPermissions
      // here to request the missing permissions, and then overriding
      // public void onRequestPermissionsResult(int requestCode, String[] permissions,
      // int[] grantResults)
      // to handle the case where the user grants the permission. See the documentation
      // for ActivityCompat#requestPermissions for more details.
      return;
      			}
      			cameraManager.openCamera(mCameraID, mCameraDeviceStateCallback, mHandler);
      		} catch (CameraAccessException e) {
      			e.printStackTrace();
      		}
      	}
     	@Override
     	public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
     			int height) {
      	}
     	@Override
     	public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
     		return false;
      	}
     	// 这个方法要注意一下,因为每有一帧画面,都会回调一次此方法
     	@Override
     	public void onSurfaceTextureUpdated(SurfaceTexture surface) {
      	}
     	private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
     		@Override
     		public void onOpened(CameraDevice camera) {
     			try {
       mCamera = camera;
       startPreview(mCamera);
      			} catch (CameraAccessException e) {
       e.printStackTrace();
      			}
      		}
     		@Override
     		public void onDisconnected(CameraDevice camera) {
      		}
     		@Override
     		public void onError(CameraDevice camera, int error) {
      		}
      	};
     	// 开始预览,主要是camera.createCaptureSession这段代码很重要,创建会话
     	private void startPreview(CameraDevice camera) throws CameraAccessException {
      		SurfaceTexture texture = mPreviewView.getSurfaceTexture();
     		// 这里设置的就是预览大小
      		texture.setDefaultBufferSize(mPreviewSize.getWidth(),mPreviewSize.getHeight());
      		Surface surface = new Surface(texture);
     		try {
     			// 设置捕获请求为预览,这里还有拍照啊,录像等
      			mPreviewBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
      		} catch (CameraAccessException e) {
      			e.printStackTrace();
      		}
     		// 就是在这里,通过这个set(key,value)方法,设置曝光啊,自动聚焦等参数!! 如下举例:
     		// mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
      		mImageReader = ImageReader.newInstance(mImageWidth, mImageHeight,
       ImageFormat.JPEG/* 此处还有很多格式,比如我所用到YUV等 */, 2/*
       * 最大的图片数,
       * mImageReader里能获取到图片数
       * ,
       * 但是实际中是2+1张图片,就是多一张
       */);
      		mImageReader.setOnImageAvailableListener(mOnImageAvailableListener,mHandler);
     		// 这里一定分别add两个surface,一个Textureview的,一个ImageReader的,如果没add,会造成没摄像头预览,或者没有ImageReader的那个回调!!
      		mPreviewBuilder.addTarget(surface);
      		mPreviewBuilder.addTarget(mImageReader.getSurface());
      		camera.createCaptureSession(
       Arrays.asList(surface, mImageReader.getSurface()),
       mSessionStateCallback, mHandler);
      	}
     	private CameraCaptureSession.StateCallback mSessionStateCallback = new CameraCaptureSession.StateCallback() {
     		@Override
     		public void onConfigured(CameraCaptureSession session) {
     			try {
       updatePreview(session);
      			} catch (CameraAccessException e) {
       e.printStackTrace();
      			}
      		}
     		@Override
     		public void onConfigureFailed(CameraCaptureSession session) {
      		}
      	};
     	private void updatePreview(CameraCaptureSession session)
     			throws CameraAccessException {
      		session.setRepeatingRequest(mPreviewBuilder.build(), null, mHandler);
      	}
     	private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
     		/**
       * 当有一张图片可用时会回调此方法,但有一点一定要注意: 一定要调用
       * reader.acquireNextImage()和close()方法,否则画面就会卡住!!!!!我被这个坑坑了好久!!!
       * 很多人可能写Demo就在这里打一个Log,结果卡住了,或者方法不能一直被回调。
       **/
     		@Override
     		public void onImageAvailable(ImageReader reader) {
     			long startTime = System.currentTimeMillis(); //起始时间
      			Image img = reader.acquireNextImage();
     			/**
       * 因为Camera2并没有Camera1的Priview回调!!!所以该怎么能到预览图像的byte[]呢?就是在这里了!!!
       * 我找了好久的办法!!!
       **/
      			ByteBuffer buffer = img.getPlanes()[0].getBuffer();
     			// 这里就是图片的byte数组了
     			byte[] bytes = new byte[buffer.remaining()];
      			buffer.get(bytes);
      			img.close();
      			Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
      			Matrix matrix = new Matrix();
      			matrix.postRotate(270);
      // matrix.postScale( 1/2, 1/2); // 长和宽放大缩小的比例
      			Bitmap bimap1 = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
     			int faceInfo[] = null;
      			Bitmap rgba = bimap1.copy(Bitmap.Config.ARGB_8888, true);
     			long endTime = System.currentTimeMillis(); //结束时间
     			int width = rgba.getWidth();
     			int height = rgba.getHeight();
     			byte[] imageDate = getPixelsRGBA(rgba);
     			long endTime2 = System.currentTimeMillis(); //结束时间
      			saveBitmap(getApplicationContext(),rgba);
      			Log.e("test", String.format("方法使用时间 %d %d ms", endTime - startTime,endTime2-startTime));
      		}
      	};
     	//提取像素点
     	private byte[] getPixelsRGBA(Bitmap image) {
     		// calculate how many bytes our image consists of
     		int bytes = image.getByteCount();
      		ByteBuffer buffer = ByteBuffer.allocate(bytes); // Create a new buffer
      		image.copyPixelsToBuffer(buffer); // Move the byte data to the buffer
     		byte[] temp = buffer.array(); // Get the underlying array containing the
     		return temp;
      	}
     	protected void onPause() {
     		if (null != mCamera) {
      			mCamera.close();
      			mCamera = null;
      		}
     		if (null != mImageReader) {
      			mImageReader.close();
      			mImageReader = null;
      		}
     		super.onPause();
      	}
      }
  
 

 

文章来源: blog.csdn.net,作者:网奇,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/jacke121/article/details/101514590

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。