Camera相机开发详解

59fe021d089ce9b93a0211f0b6f124cf.png

image

Surface

什么是Surface?源码中是这样描述的:


* Handle onto a raw buffer that is being managed by the screen compositor.

 *

 * <p>A Surface is generally created by or from a consumer of image buffers (such as a

 * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or

 * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as

 * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL},

 * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or

 * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw

 * into.</p>

简单翻译一下,大概意思就是:

Surfaces是用来处理屏幕显示内容合成器所管理的原始缓存区的工具。它通常由图像缓冲区的消费者来创建(如:SurfaceTexture,MediaRecorder),然后被移交给生产者(如:MediaPlayer)或者是显示到其上(如:CameraDevice)

SurfaceHolder

源码描述:


* Abstract interface to someone holding a display surface.  Allows you to

 * control the surface size and format, edit the pixels in the surface, and

 * monitor changes to the surface.  This interface is typically available

 * through the {@link SurfaceView} class.

简单翻译一下:

一个抽象接口,给持有surface的对象使用。它可以控制surface的大小和格式,编辑surface中的像素,以及监听surface的变化。这个接口通常通过SurfaceView类获得

SurfaceHolder中有一个Callbcak接口,它有3个回调方法

  • surfaceCreated(SurfaceHolder holder)

    surface第一次创建时回调

  • surfaceChanged(SurfaceHolder holder, int format, int width,

    int height)

    surface变化的时候回调(格式/大小)

  • surfaceDestroyed(SurfaceHolder holder)

    surface销毁的时候回调

这个回调接口就是源码中所提到的 “monitor changes to the surface”(监听surface的变化),我们后面会用到

SurfaceView

源码描述:


* Provides a dedicated drawing surface embedded inside of a view hierarchy.

 * You can control the format of this surface and, if you like, its size; the

 * SurfaceView takes care of placing the surface at the correct location on the

 * screen

大致翻译一下:

SurfaceView提供了嵌入视图层级中的专用surface。你可以控制surface的格式或大小。SurfaceView负责把surface显示在屏幕的正确位置

SurfaceView继承自View,其中有两个成员变量,一个是Surface对象,一个是SuraceHolder对象。(请参考上面第二幅关系图)

  • SurfaceView把Surface显示在屏幕上

  • SurfaceView通过SuraceHolder告诉我们Surface的状态(创建、变化、销毁)

  • 通过getHolder()方法获得当前SurfaceView的SuraceHolder对象,然后就可以对SuraceHolder对象添加回调来监听Surface的状态

SurfaceView小结

  1. SurfaceView是一个view对象,用于在屏幕上显示相机的预览画面

  2. SurfaceView中有两个对象,Surface和SuraceHolder。我们通过SuraceHolder中的回调可以知道Surface的状态(创建、变化、销毁)

  3. 通过getHolder()方法获得当前SurfaceView的SuraceHolder对象

二、Camera


概览图

Camera类中主要的内部类和接口,如下图:

1233ff11be9a3a5ed70ea8bd32a8709b.png

image

Camera类中有很多内部类和方法,下面分别对这些类和方法做介绍:

Camera类中的内部类

CameraInfo

CameraInfo类用来描述相机信息,通过Camera类中getCameraInfo(int cameraId, CameraInfo cameraInfo)方法获得,主要包括以下两个成员变量:

  • facing

    facing 代表相机的方向,它的值只能是CAMERA_FACING_BACK(后置摄像头) 或者CAMERA_FACING_FRONT(前置摄像头)。

CAMERA_FACING_BACK 和 CAMERA_FACING_FRONT 是CameraInfo类中的静态变量

  • orientation

    这个就比较有意思了,也比较重要,源码中是这样描述的:


* <p>The orientation of the camera image. The value is the angle that the

         * camera image needs to be rotated clockwise so it shows correctly on

         * the display in its natural orientation. It should be 0, 90, 180, or 270.</p>

         *

         * <p>For example, suppose a device has a naturally tall screen. The

         * back-facing camera sensor is mounted in landscape. You are looking at

         * the screen. If the top side of the camera sensor is aligned with the

         * right edge of the screen in natural orientation, the value should be

         * 90. If the top side of a front-facing camera sensor is aligned with

         * the right of the screen, the value should be 270.</p>

翻译一下,大概意思是:

orientation是相机采集图片的角度。这个值是相机所采集的图片需要顺时针旋转至自然方向的角度值。它必须是0,90,180或270中的一个。

举个栗子:

假如你自然地竖着拿着手机(就是自拍时候的样子…),后置摄像头的传感器在手机里是水平方向的,你现在看着手机,如果传感器的顶部在自然方向上手机屏幕的右边(此时,手机是竖屏,传感器是横屏),那么这个orientation的值就是90。如果前置摄像头的传感器顶部在手机屏幕右边,那么这个值就是270.

  • setDisplayOrientation

    源码描述如下:


* Set the clockwise rotation of preview display in degrees. This affects

     * the preview frames and the picture displayed after snapshot. This method

     * is useful for portrait mode applications. Note that preview display of

     * front-facing cameras is flipped horizontally before the rotation, that

     * is, the image is reflected along the central vertical axis of the camera

     * sensor. So the users can see themselves as looking into a mirror.

翻译一下:


设置预览画面顺时针旋转的角度。这个方法会影响预览图像和拍照后显示的照片。这个方法对竖屏应用非常有用。

注意,前置摄像头在进行角度旋转之前,图像会进行一个水平的镜像翻转。

所以用户在看预览图像的时候就像照镜子,看到的是现实的水平方向的镜像。

注:setDisplayOrientation(int degrees)是Camea类中的一个方法,之所以穿插在这里来讲,是为了和上面提到的orientation做一个统一讲解,因为这两个都涉及到了方向问题

看了上面的介绍是不是有点懵逼。。。没关系,下面给小伙伴们详细介绍一下Android手机上几个方向的概念以及在使用Camera过程中会遇到的方向问题:

注:如果你是第一次使用Camera的话,首先要了解以下几点:

  1. 相机图像数据都是来自于相机硬件的图像传感器(Image Sensor),这个Sensor被固定到手机之后是有一个默认的取景方向,且不会改变
  1. 相机在预览的时候是有一个预览方向的,可以通过setDisplayOrientation()设置
  1. 相机所采集的照片也是有一个方向的(就是上面刚刚提到的orientation),这个方向与预览时的方向互不相干
  • 屏幕坐标:在Android系统中,屏幕的左上角是坐标系统的原点(0,0)坐标。原点向右延伸是X轴正方向,原点向下延伸是Y轴正方向

  • 自然方向:每个设备都有一个自然方向,手机和平板的自然方向不同。手机的自然方向是portrait(竖屏),平板的自然方向是landscape(横屏)

  • 图像传感器(Image Sensor)方向:手机相机的图像数据都是来自于摄像头硬件的图像传感器,这个传感器在被固定到手机上后有一个默认的取景方向

c221503496b70d0927ed5aaee54b51ee.png

image

  • 相机的预览方向:将图像传感器捕获的图像,显示在屏幕上的方向。在默认情况下,与图像传感器方向一致。在相机API中可以通过setDisplayOrientation()设置相机预览方向。在默认情况下,这个值为0,与图像传感器方向一致

51d01588089dc616315eac6fa054f3d2.png

image

  • 相机采集的图像方向

    相机采集图像后需要进行顺时针旋转的角度,即上面介绍的orientation的值:

fcbf14c522ad6c0b69024481230e8ebd.png

image

这里先做个小结:

  • 绝大部分安卓手机中图像传感器方向是横向的,且不能改变,所以orientation是90或是270,也就是说,当点击拍照后保存图片的时候,需要对图片做旋转处理,使其为"自然方向"。(可能存在一些特殊的定制或是能外接摄像头的安卓机,他们的orientation会是0或者180)

  • 通过setDisplayOrientation方法设置预览方向,使预览画面为"自然方向"。前置摄像头在进行角度旋转之前,图像会进行一个水平的镜像翻转,所以用户在看预览图像的时候就像照镜子一样。

这些都是些理论,在下篇文章中,会通过实例代码一步步地验证。

好,我们接着看Camera类中的内部类:

Size

图片大小,里面包含两个变量:width和height(图片的宽和高)

Parameters

Parameters是相机服务设置,不同的相机可能是不相同的。比如相机所支持的图片大小,对焦模式等等。下面介绍一下这个类中常用的方法

  • getSupportedPreviewSizes()

    获得相机支持的预览图片大小,返回值是一个List数组

  • setPreviewSize(int width, int height)

    设置相机预览图片的大小

  • getSupportedPreviewFormats()

    获得相机支持的图片预览格式,所有的相机都支持ImageFormat.NV21

    更多的图片格式可以自行百度或是查看ImageFormat类

  • setPreviewFormat(int pixel_format)

    设置预览图片的格式

  • getSupportedPictureSizes()

    获得相机支持的采集的图片大小(即拍照后保存的图片的大小)

  • setPictureSize(int width, int height)

    设置保存的图片的大小

  • getSupportedPictureFormats()

    获得相机支持的图片格式

  • setPictureFormat(int pixel_format)

    设置保存的图片的格式

  • getSupportedFocusModes()

    获得相机支持的对焦模式

  • setFocusMode(String value)

    设置相机的对焦模式

  • getMaxNumDetectedFaces()

    返回当前相机所支持的最大的人脸检测个数

    比如,我的手机是vivo x9,后置摄像头所支持最大的人脸检测个数是10,也就是说当画面中人脸数超过10个的时候,只能检测到10张人脸

PreviewCallback

PreviewCallback是一个抽象接口

  • void onPreviewFrame(byte[] data, Camera camera)

    通过onPreviewFrame方法来获取到相机预览的数据,第一个参数data,就是相机预览到的原始数据。

这些预览到的原始数据是非常有用的,比如我们可以保存下来当做一张照片,还有很多第三方的人脸检测及静默活体检测的sdk,都需要我们把相机预览的数据实时地传递过去。

Face

Face类用来描述通过Camera的人脸检测功能检测到的人脸信息

  • rect

    rect 是一个Rect对象,它所表示的就是检测到的人脸的区域。

注意:这个Rect对象中的坐标系并不是安卓屏幕的坐标系,需要进行转换后才能使用,具体会在后面实现人脸检测功能的时候详细介绍

  • score

    检测到的人脸的可信度,范围是1 到100

  • leftEye

    leftEye 是一个Point对象,表示检测到的左眼的位置坐标

  • rightEye

    rightEye是一个Point对象,表示检测到的右眼的位置坐标

  • mouth

    mouth是一个Point对象,表示检测到的嘴的位置坐标

leftEye ,rightEye和mouth这3个人脸中关键点,并不是所有相机都支持的,如果相机不支持的话,这3个的值为null

FaceDetectionListener

这是一个抽象接口,当开始人脸检测时开始回调

  • onFaceDetection(Face[] faces, Camera camera)

    第一参数代表检测到的人脸,是一个Face数组(画面内可能存在多张人脸)

Camera类中的方法

  • getNumberOfCameras()

    返回当前设备上可用的摄像头个数

  • open()

    使用当前设备上第一个后置摄像头创建一个Camera对象。如果当前设备没有后置摄像头,则返回值为null

  • open(int cameraId)

    使用传入id所表示的摄像头创建一个Camera对象,如果id所表示的摄像头已经被打开,则会抛出异常

设备上每一个物理摄像都是有一个id的,id从0开始,到getNumberOfCameras() - 1 结束

例如,一般的手机上都有前后两个摄像头,那么后置摄像头id就是0,前置摄像头id就是1

  • getCameraInfo(int cameraId, CameraInfo cameraInfo)

    返回指定id所表示的摄像头的信息

  • setDisplayOrientation(int degrees)

    设置相机预览画面旋转的角度

    上面已经讲过,见图五

  • setPreviewDisplay(SurfaceHolder holder)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值