2022年android摄像头 .pdf

上传人:C****o 文档编号:32488497 上传时间:2022-08-09 格式:PDF 页数:15 大小:241.46KB
返回 下载 相关 举报
2022年android摄像头 .pdf_第1页
第1页 / 共15页
2022年android摄像头 .pdf_第2页
第2页 / 共15页
点击查看更多>>
资源描述

《2022年android摄像头 .pdf》由会员分享,可在线阅读,更多相关《2022年android摄像头 .pdf(15页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、在 android的模拟器上面调用系统的摄像机会出现异常的现象,会自动退出, 这可能和模拟器有关, 模拟器无法使用系统的硬件,就像重力感应和方向感应系统一样都无法使用,甚至是 GPS导航系统也无法使用,好像有个第三方的组织,已经模拟出来模拟器上使用重力感应。但是我没有真正的看到,下面的这几段是一本书上面写的android上面使用模拟器的例子。这个示例将显示预览图像,在图像上点击则触发拍照操作,拍照成功后显示所拍的照片,然后点击Start菜单可以继续拍照。首先通过OPhone开发工具(ODT)创建一个OPhone项目,填写基本信息后ODT会自动创建一个srcorggoodevcameraCame

2、raActivity.java文件和reslayoutmain.xml文件。把main.xml文件内容修改为如下:view plaincopy to clipboardprint? 1. 2. 7. 10. 13. SurfaceView 用来预览图像,ImageView 用来显示所拍的照片。这里也需读者会问,为什么要使用SurfaceView 来预览图像?使用其他的View不可以吗?要回答这个问题,需要了解下SurfaceView 的作用,关于SurfaceView 的详细介绍已超出了本教程的范围,我们会在后续教程中来详细介绍SurfaceView ,这里只做简要介绍。在通常情况下,OPho

3、ne程序中的View都是在同一个GUI线程中绘制的,该线程也是接收用户交互事件的线程(例如:按钮点击事件)。从另外的线程修改GUI元素是不可以的,如果要迅速的更新UI显示该如何办?显然在主线程中还需要处理其他事件,不适合做这件事情,所以OPhone提供了SurfaceView 来满足这种需求。一个SurfaceView 包装一个Surface对象(通过SurfaceHolder操作该对象)而不是Canvas对象,这就是关键所在,Surface可以在其他线程中绘制,这对于周期性更新和要求高帧率的场景来说是很有用的,特别是在游戏开发中。Surface中包含了当前UI的原生数据(raw data),

4、在不同的软件和硬件条件下对这些数据的处理是不一样的,这就可以通过一些设置来加速图形的绘制,可以通过SurfaceHolder的setType函数来设置, 目前接收如下的参数:SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 15 页 - - - - - - -

5、- - SURFACE_TYPE_GPU:适用于GPU加速的Surface SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。如果在这里设置了上面三种类型则可以发现不会出现预览图像,在和Camera底层的预览机制实现有关,如果对预览有特殊要求的可以现实PreviewCallback 接口来自己处理。关于SurfaceView先简单介绍到这里,下面来继续看看如何在代码中实现。修改CameraAc

6、tivity类使其实现如下接口:view plaincopy to clipboardprint? 1. android.view.SurfaceHolder.Callback 2. android.view.View.OnClickListener 原创android 之摄像头用 google查了一下camera方面的资料, 前几页的检索内容居然一模一样的,真是浪费时间,严重鄙视一下。既然要用到硬件肯定要牵涉到权限,在 Mainifest.xml中加入 camera的权限: 调用 camera最简单的办法是调用系统的功能,然后通过 onActivityResult方法获得图像数据。不是太习惯

7、用android的 xml 配置文件,但是为了代码简单,先加一个layout.xml 系统 camera的 uri 为:android.media.action.IMAGE_CAPTUREfinal int TAKE_PICTURE = 1; ImageView iv;private void test1()iv = new ImageView(this);(FrameLayout)findViewById(R.id.FrameLayout01).addView(iv);Button buttonClick = (Button)findViewById(R.id.Button01);butto

8、nClick.setOnClickListener(new OnClickListener() Override public void onClick(View arg0) startActivityForResult(new Intent(android.media.action.IMAGE_CAPTURE), TAKE_PICTURE); );protected void onActivityResult(int requestCode, int resultCode, Intent data) if (requestCode = TAKE_PICTURE) if (resultCode

9、 = RESULT_OK) Bitmap b = (Bitmap) data.getExtras().get(data); iv.setImageBitmap(b); 系统功能很简单,呵呵,不过不能满足俺小小的控制欲,看看camera类能干些什么。首先扫描了一下camera ,感觉 camera主要是用到几个接口:1. 需要 SurfaceHolder类来显示图像, 并获取 SurfaceHolder类传递给 Camera,Camera以后通过该Holder对图像进行处理。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心

10、整理 - - - - - - - 第 3 页,共 15 页 - - - - - - - - - 所以程序中需要SurfaceView子类,并实现SurfaceHolder.Callback接口:public void surfaceChanged(SurfaceHolder holder, int format, int width,int height)public void surfaceCreated(SurfaceHolder holder)public void surfaceDestroyed(SurfaceHolder holder)如: public class Preview

11、 extends SurfaceView implements SurfaceHolder.Callback 2. 拍摄相片主要用到如下方法:public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg)方法中的参数是几个回调接口:ShutterCallbackvoid onShutter();拍照时调用该接口,用于按下拍摄按钮后播放声音等操作PictureCallbackvoid onPictureTaken(byte data, Camera camera);

12、拍照时调用该接口,data 为拍摄照片数据,camera为 Camera类自身takePicture方法中有两个PictureCallback, 看参数名好像一个是原始数据,一个是 jpeg数据。3. 还有一个预览方式PreviewCallbackvoid onPreviewFrame(byte data, Camera camera);该接口可以获取摄像头每一帧的图像数据此外此外还有几个辅助方法:startPreview() stopPreview() previewEnabled() 4. 其它方法:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - -

13、- - - - - - 名师精心整理 - - - - - - - 第 4 页,共 15 页 - - - - - - - - - 自动对焦AutoFocusCallbackvoid onAutoFocus(boolean success, Camera camera);摄像头自动对焦,success表示自动对焦是否成功 ErrorCallbackvoid onError(int error, Camera camera)摄像头发生错误是调用该接口,CAMERA_ERROR_UNKNOWN CAMERA_ERROR_SERVER_DIED 表示媒体服务已经当掉,需要释放Camera重新启动setP

14、arameters(Parameters params) 设置摄像头参数先来做一个最简单的测试:用来表现图像的SurfaceView子类, Android的例子里面有一个,直接拿过来用用:class camerView extends SurfaceView implements SurfaceHolder.Callback SurfaceHolder mHolder; Camera mCamera; public camerView(Context context) super(context); mHolder = this.getHolder(); mHolder.addCallback

15、(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewSize(width, height); mCamera.setParameters(parameters); mCamera.startPrev

16、iew(); public void surfaceCreated(SurfaceHolder holder) mCamera = Camera.open(); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 15 页 - - - - - - - - - try mCamera.setPreviewDisplay(holder); catch (IOException exception) mCamera.release(); mCamera = null; public

17、 void surfaceDestroyed(SurfaceHolder holder) mCamera.stopPreview(); mCamera.release(); mCamera = null; public void draw(Canvas canvas) super.draw(canvas); Log.d(=, draw); 内容比较简单,Camera的管理都跟camerView的几个接口绑在一块。下来把 View 加到 Active中去,同时用用 takePicture方法:private void test2() cv = new camerView(this); Relat

18、iveLayout relay = (RelativeLayout)findViewById(R.id.FrameLayout01); relay.addView(cv); buttonClick = (Button)findViewById(R.id.Button01); buttonClick.setOnClickListener(new OnClickListener() public void onClick(View arg0) cv.mCamera.takePicture( new ShutterCallback() public void onShutter() Log.d(=,

19、 onShutter); , new PictureCallback() public void onPictureTaken(byte data, Camera camera) Log.d(=, raw: + (data = null ? null : data.length); ,/raw new PictureCallback() public void onPictureTaken(byte data, Camera camera) Log.d(=, postview: + (data = null ? null : 名师资料总结 - - -精品资料欢迎下载 - - - - - - -

20、 - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 15 页 - - - - - - - - - data.length); , /postview new PictureCallback() public void onPictureTaken(byte data, Camera camera) Log.d(=, jpeg: + (data = null ? null : data.length); / jpeg ); ); 这样所有的代码就完成了,在模拟器上点击test按钮,在log 中可以看到:=onShutter =raw:null

21、=jpeg:18474 很奇怪的是 camerView中的 =draw没有输出,说明View 不进行绘制,那么摄像图像是怎么出来的呢?源代码中是调用本地方法,懒得去看C 代码,不想钻得太深,娱乐而已。上网查了一半天也没有搞明白,感觉是通过SurfaceHolder获得 View 的 Canvas对象,直接进行绘制,Holder中没有 View 的引用,当然不会再去调用View 的 draw方法了。最后在网上搜到文章一篇,对这个原因有一点说明,Copy 之,以防后面忘记:在通常情况下,OPhone程序中的View 都是在同一个GUI 线程中绘制的,该线程也是接收用户交互事件的线程(例如: 按钮点

22、击事件) 。 从另外的线程修改 GUI 元素是不可以的,如果要迅速的更新UI 显示该如何办?显然在主线程中还需要处理其他事件,不适合做这件事情,所以OPhone提供了SurfaceView 来满足这种需求。一个SurfaceView 包装一个 Surface对象 (通过 SurfaceHolder操作该对象 )而不是 Canvas对象,这就是关键所在,Surface可以在其他线程中绘制, 这对于周期性更新和要求高帧率的场景来说是很有用的,特别是在游戏开发中。Surface中包含了当前UI 的原生数据 (raw data),在不同的软件和硬件条件下对这些数据的处理是不一样的,这就可以通过一些设置

23、来加速图形的绘制,可以通过 SurfaceHolder的 setType函数来设置,目前接收如下的参数:SURFACE_TYPE_NORMAL:用 RAM 缓存原生数据的普通Surface SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface SURFACE_TYPE_GPU:适用于GPU 加速的 Surface SURFACE_TYPE_PUSH_BUFFERS:表明该 Surface不包含原生数据, Surface用到的数据由其他对象提供,在 Camera图像预览中就使用该类型的Surface, 有 Camer

24、a名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 15 页 - - - - - - - - - 负责提供给预览Surface数 据,这样图像预览会比较流畅。如果在这里设置了上面三种类型则可以发现不会出现预览图像,在和Camera底层的预览机制实现有关,如果对预览有特殊要求的可以现实PreviewCallback 接口来自己处理。如果想在图像上叠加一些文字等透明信息的时候,总不能也像j2me一样地处理吧。后面看到一篇文章介绍,直接将一个View 叠加到 Camera上就可以

25、了,开始还不相信,后面实在找不到其它办法,试一试看看:在 test2()中加入TextView tv = new TextView(this); tv.setText(test); RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); lp.addRule(RelativeLayout.CENTER_IN_PARENT); relay.addView(tv, lp);果然

26、可以。呵呵,分了一下神,再回来看看Camera。既然 jpeg数据有输出,看看jpeg是什么内容,new PictureCallback() public void onPictureTaken(byte data, Camera camera) Log.d(=, jpeg: + (data = null ? null : data.length); / jpeg在 jpeg的回调接口中添加内容Log.d(=, jpeg: + (data = null ? null : data.length); cv.setVisibility(View.INVISIBLE); ImageView iv =

27、 new ImageView(test.this); Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); iv.setImageBitmap(bitmap); relay.addView(iv);其中的 test是类名,另外需要把relay改成 final变量:final RelativeLayout relay = (RelativeLayout)findViewById(R.id.FrameLayout01);呵呵,又看到那幅熟悉的图片了,帅。名师资料总结 - - -精品资料欢迎下载 - - - - -

28、- - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 15 页 - - - - - - - - - raw 数据没有输出,网上也有人提问,外网被屏蔽了看不到详细的信息,那就此处不表下次再说了。看看能不能设置一下参数就可以有输出了,在好奇的驱使下,又试了一下设置参数。从 log 中可以看到Parameters预设的参数:picture-format=jpeg picture-preview=yuv422sp 很可惜,设置为其它的参数系统都报错,玩不转, 郁闷,看来要在摄像头这一块抱太多的遗憾了。算了,看看Camera最后一点功能吧,获取帧数

29、据:mCamera.setPreviewCallback(new PreviewCallback() public void onPreviewFrame(byte data, Camera camera) Log.d(=, onPreviewFrame); );其中的 data是 yuv 格式的,需要对其解码:static public void decodeYUV420SP(byte rgbBuf, byte yuv420sp, int width, int height) final int frameSize = width * height; if (rgbBuf = null) t

30、hrow new NullPointerException(buffer rgbBuf is null); if (rgbBuf.length frameSize * 3) throw new IllegalArgumentException(buffer rgbBuf size + rgbBuf.length + minimum + frameSize * 3); if (yuv420sp = null) throw new NullPointerException(buffer yuv420sp is null); if (yuv420sp.length frameSize * 3 / 2

31、) throw new IllegalArgumentException(buffer yuv420sp size + yuv420sp.length + minimum + frameSize * 3 / 2); int i = 0, y = 0; int uvp = 0, u = 0, v = 0; int y1192 = 0, r = 0, g = 0, b = 0; for (int j = 0, yp = 0; j 1) * width; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - -

32、 - - 第 9 页,共 15 页 - - - - - - - - - u = 0; v = 0; for (i = 0; i width; i+, yp+) y = (0 xff & (int) yuv420spyp) - 16; if (y 0) y = 0; if (i & 1) = 0) v = (0 xff & yuv420spuvp+) - 128; u = (0 xff & yuv420spuvp+) - 128; y1192 = 1192 * y; r = (y1192 + 1634 * v); g = (y1192 - 833 * v - 400 * u); b = (y11

33、92 + 2066 * u); if (r 262143) r = 262143; if (g 262143) g = 262143; if (b 262143) b = 262143; rgbBufyp * 3 = (byte)(r 10); rgbBufyp * 3 + 1 = (byte)(g 10); rgbBufyp * 3 + 2 = (byte)(b 10); 摄像头这一块android虽然给了一个接口,但是实现还是各个厂家自己实现的,所以不同的机型处理方式还不一致,android camera 源码分析(基于应用)这里主要是针对Ophone 进行介绍的,当然结合了 androi

34、d 的源码(以下出现均为android2.2源码)。首先在 Ophone 中也是通过android.hardware.Camera类来控制摄像头设备的,要使用只有通过android.hardware.Camera.open()来打开。try mCameraDevice = android.hardware.Camera.open(); catch (RuntimeException e) Log.e(TAG, fail to connect Camera, e); throw new CameraHardwareException(e); 另外 Ophone 还提供了一些接口来给予回调,控制C

35、amera 的状态,名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 15 页 - - - - - - - - - 分别是:1.android.hardware.Camera.ErrorCallback:摄像头出错的时候调用,这个接口具有一个 void onError(int error,Camera camera)函数;其中,前者表示数据类型,取值是Camera 类中的常量CAMERA_ERROR_UNKNOWN或者是CAMERA_ERROR_SERVICE_DIED;

36、前者是不明错误,后者是表示服务已经关闭,在这种情况下需要释放当前的Camera对象,然后再初始化一个。private static final class ErrorCallback implements android.hardware.Camera.ErrorCallback public void onError(int error, android.hardware.Camera camera) if (error = android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) mMediaServerDied = true; Log.v(TAG

37、, media server died); 2.android.hardware.camera.PreviewCallback:在图像预览时调用,这个接口有一个void onPreviewFrame(byte data,Camera camera);参数 data 为每帧图像的数据流。我们可以根据实际需要来实现这个接口。3.android.hardware.Camera.ShutterCallback:在图像预览的时候调用,这个接口具有一个void onShutter();可以在改函数中通知用户快门已经关闭,例如播放一个声音。private final class ShutterCallbac

38、k implements android.hardware.Camera.ShutterCallback public void onShutter() mShutterCallbackTime = System.currentTimeMillis(); mShutterLag = mShutterCallbackTime - mCaptureStartTime; Log.v(TAG, mShutterLag = + mShutterLag + ms); clearFocusState(); 4.android.hardware.Camera.PictureCallback:当拍摄相片的时候调

39、用,该接口具有一个void onPictureTaken(byte data,Camera camera)函数 ;参数和预览的一样。在 android 中主要有三个类实现了这个接口,分别是PostViewPictureCallback、 RawPictureCallback、JepgPictureCallback。我们可以根据需要定义自己需要的类。5.android.hardware.Camera.AutoFocusCallback:当自动对焦时候调用,该接口具有一个void onAutoFocus(boolean focused,Camera camera)函数 ; private fina

40、l class AutoFocusCallback implements android.hardware.Camera.AutoFocusCallback public void onAutoFocus(boolean focused, android.hardware.Camera camera) mFocusCallbackTime = System.currentTimeMillis(); mAutoFocusTime = mFocusCallbackTime - mFocusStartTime; Log.v(TAG, mAutoFocusTime = + mAutoFocusTime

41、 + ms); if (mFocusState = FOCUSING_SNAP_ON_FINISH) / Take the picture no matter focus succeeds or fails. No need / to play the AF sound if were about to play the shutter / sound. if (focused) mFocusState = FOCUS_SUCCESS; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第

42、 11 页,共 15 页 - - - - - - - - - else mFocusState = FOCUS_FAIL; mImageCapture.onSnap(); else if (mFocusState = FOCUSING) / User is half-pressing the focus key. Play the focus tone. / Do not take the picture now. ToneGenerator tg = mFocusToneGenerator; if (tg != null) tg.startTone(ToneGenerator.TONE_PR

43、OP_BEEP2); if (focused) mFocusState = FOCUS_SUCCESS; else mFocusState = FOCUS_FAIL; else if (mFocusState = FOCUS_NOT_STARTED) / User has released the focus key before focus completes. / Do nothing. updateFocusIndicator(); 6.还提供了放大缩小的监听器android.hardware.Camera.OnZoomChangeListener。private final class

44、 ZoomListener implements android.hardware.Camera.OnZoomChangeListener public void onZoomChange(int value, boolean stopped, android.hardware.Camera camera) Log.v(TAG, Zoom changed: value= + value + . stopped= + stopped); mZoomValue = value; / Keep mParameters up to date. We do not getParameter again

45、in / takePicture. If we do not do this, wrong zoom value will be set. mParameters.setZoom(value); / We only care if the zoom is stopped. mZooming is set to true when / we start smooth zoom. if (stopped & mZoomState != ZOOM_STOPPED) if (value != mTargetZoomValue) mCameraDevice.startSmoothZoom(mTarget

46、ZoomValue); mZoomState = ZOOM_START; else mZoomState = ZOOM_STOPPED; 当取得照片的数据流后可以通过BitmapFactory的 decodeByteArray()函数来解析图片。另外还可以通过Camera 对象的 getParameters()函数来得到一个android.hardware.Camera.Parameters 对象, Parameters提供了一些接口来设置Camera的属性:1.setPictureFormat(int pixel_format):设置图片的格式,其取值为PixelFormat YCbCr_4

47、20_SP、 PixelFormatRGB_565或者 PixelFormatJPEG。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 15 页 - - - - - - - - - 2.setPreviewFormat(int pixel_format):设置图片的预览格式,取值如上。3.setPictureSize(int width,int height):设置图片的高度和宽度,单位为像素。4.setPreviewSize(int width,int height)

48、:设置预览的高度和宽度,取值如上。5.setPreviewFrameRate(int fps):设置图片预览的帧速。在设置好 Camera 的参数后, 可以通过函数void startPreview()开始预览图像、void stopPreview()结束预览,通过autoFocus(AutoFocusCallback cb)来自动对焦, 最后可以通过takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg)函数来拍照。该函数有三个参数,分别为快门回调接口、原生图像数据接口和压缩格式图片数据接口

49、。如果数据格式不存在的话数据流为空,如果不需要实现这些接口则这些参数取值可以为null。Android平台硬件调试之Camera篇之前一段时间有幸在高通android 平台上调试 2 款 camera sensor , 一款是 OV 的 5M YUV sensor ,支持 jpeg out ,同时也支持AF,调试比较比较简单,因为别的项目已经在使用了,只是把相关的驱动移植过来就好;另一款是Samsung 的一款比较新的3M YUV FF sensor,在最新项目中要使用的,本文以调试该sensor 为例,从底层驱动的角度分享一下高通android 平台下调试camera 的经验,而对于高通平台

50、camera 部分的架构以及原理不做过多的介绍。一、准备工作从项目中看,在硬件(板子)ready 前,软件部分是要准备好的。单独从底层驱动来看,软件部分可以分为2 个部分,一个是高通平台相关的,再一个就是sensor 部分的,通常的做法就是把sensor 相关的设定移植到高通平台的框架之中。这样就需要先拿到sensor 的spec 以及厂商提供的sensor register setting file。Spec 的用途是清楚高通平台和sensor通讯(读写寄存器) 的时序以及相关参数设定;而厂商提供的setting file则是在使用camera各个功能( preview 、snapshot.

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com