哈工大计算机科学与技术学院软件基础教研室Android=人+计算普适环境授课教师:李治军lizhijun_os@hit.edu.cn综合楼417室第4章视觉感知与Android实践Chapter4:VisionSensing&AndroidPractice-2-Android&PervasiveComputing图像(视觉)感知,你能想到?仍是面向人感知应用基本思路:感知(Sensing)测量(Measuring)分类(Classification)推演(Inference)构建应用(Apps)感知:读取时域信息,即像素信息(二维函数)测量:分块处理(块大小),频域变化,小波变换等分类:寻找边界,识别对象等(仍需要ML)推演:认识目标、Gesture、SocialEvent等应用:将无数个智能手机组合成为城市的眼睛(MobileComputerVision,MCV)-3-Android&PervasiveComputing计算机视觉(ComputerVision)CV就是用计算机来对humanvision建模、替代根据图片集合重建物理世界的场景scene/modelFromImageto(Knowledgeofthe)World在机器人、智能系统、自动化中广泛应用…在物理世界模型中抽取出对检测和控制有用的信息-4-Android&PervasiveComputing计算机视觉(ComputerVision)Computervision综合了计算机科学,数学,物理学,生物学,认知科学等多个学科很有趣、同时也很难-5-Android&PervasiveComputing感知—读取基础(raw)数据-6-Android&PervasiveComputingAndroid图像数据采集就是用手机拍照怎么下手?看一看核心代码肯定还是Manager或封装好的对象privateCameracamera;camera=Camera.open();...camera.takePicture(shutterCallback,null,jpegCallback);...camera.release();//释放资源camera=null;-7-Android&PervasiveComputingAndroid图像采集的细节关键:camera.takePicture,核心是三个参数第一个参数:在图像被捕获时回调,通常通过音效表明拍摄成功第二个参数:图像捕获时被调用,图片的原始数据通过byte[]传入回调方法,可忽略第三个参数:生成JPEG格式图片数据时被调用,JPEG数据通过byte[]传入回调方法camera.takePicture(shutterCallback,null,jpegCallback);privateShutterCallbackshutterCallback=newShutterCallback(){...}privatePictureCallbackjpegCallback=newPictureCallback(){...}-8-Android&PervasiveComputingAndroid图像采集的细节第一个回调:shutterCallbackprivateShutterCallbackshutterCallback=newShutterCallback(){publicvoidonShutter(){if(tone==null)//发出提示用户的声音tone=newToneGenerator(AudioManager.STREAM_MUSIC,ToneGenerator.MAX_VOLUME);tone.startTone(ToneGenerator.TONE_PROP_BEEP2);}};快门按下的时候onShutter()被回调privateToneGeneratortone;Android让手机应用开发变得很容易…Android已经封装好ToneGenerator产生铃声-9-Android&PervasiveComputingAndroid图像采集的细节第二个回调:rawCallbackprivatePictureCallbackrawCallback=newPictureCallback(){publicvoidonPictureTaken(byte[]data,Cameracam){Stringpath=save(data);}};得到图像数据时调用privateStringsave(byte[]data){Stringpath=/sdcard/+System.currentTimeMillis()+.raw;Filefile=newFile(path);if(!file.exists())file.createNewFile();FileOutputStreamfos=newFileOutputStream(file);fos.write(data);fos.close();-10-Android&PervasiveComputingAndroid图像采集的细节第三个回调:jpegCallbackprivatePictureCallbackjpegCallback=newPictureCallback(){publicvoidonPictureTaken(byte[]data,Cameracamera){Stringpath=save(data);}};保存成xx.jpg文件没有经过压缩一个标准,压缩率极高-11-Android&PervasiveComputingAndroid图像采集的细节现在运行不好使!classCameraPreviewextendsSurfaceView{SurfaceHoldermHolder;publicCameraPreview(Contextcontext){super(context);mHolder=getHolder();}publicvoidsurfaceCreated(SurfaceHolderholder){camera=Camera.open();try{camera.setPreviewDisplay(holder);}}publicvoidsurfaceChanged(...){camera.setParameters(parameters);camera.startPreview();}}Takepicture以preview为基础-12-Android&PervasiveComputingAndroid图像采集的细节类CameraPreview的使用!publicclassCameraActivityextendsActivity{privateCameraPreviewpreview;privateCameracamera;publicvoidonCreate(BundlesavedInstanceState){preview=newCameraPreview(this);setContentView(preview);}需要定义拍照按钮!publicbooleanonCreateOptionsMenu(Menumenu){menu.add(0,OPTION_SNAPSHOT,0,R.string.snapshot);returnsuper.onCreateOptionsMenu(menu);}增加系统菜单项-13-Android&PervasiveComputingAndroid运行实例照一个图片试一试(捕获菜单选择)publicbooleanonOptionsItemSelected(MenuItemitem){switch(item.getItemId()){caseOPTION_SNAPSHOT:camera.takePicture(shutterCallback,rawCallback,jpegCallback);在真机上试一试,当然别忘了把权限打开uses-permissionandroid:name=android.permission.CAMERA/FF是JPEG文件的标记,D8是图像开始C4:霍夫曼表;C0:帧开始;DA扫描线开始-14-Android&PervasiveComputingAndroid图像采集中的RawdataRawdata对后续图像处理及Vision很重要takePicture中的rawCallback返回的data总是空的takePicture实际上是将preview中捕获的某个image保存下来要想在Android上获取图像的Rawdata?需对Android的深层进行学习!!AndroidMediaFramework-15-Android&PervasiveComputingAndroid的MediaFramework-16-Android&PervasiveComputingAndroid中的Camera-17-Android&PervasiveComputingAndroid中Camera工作的具体过程(1)这个故事需要从内核说起:Video4linux2(简称V4L2),是linux中关于视频设备的内核驱动从Libraries向上的一大堆东西只是应用程序而已什么东西接通了应用和内核?JavaApplication最终依靠什么获取Camera数据?只能是Linux向上层提供的系统调用intfd=open(“/dev/video0”,O_RDWR);-18-Android&PervasiveComputingAndroid中Camera工作的具体过程(2)OpenCamera对应的文件以后会……intfd=open(“/dev/video0”,O_RDWR);structv4l2_formatfmt;fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;ioctl(fd,VIDIOC_STREAMON,&type);//开始捕捉图像数据…V4L2_PIX_FMT_YUYV就是YUV4:2:2两个像素4个字节:每个点有8bit的亮度值(Y),每2个点有一个色差(Cr和Cb)-19-Android&PervasiveComputingAndroid中Camera工作的具体过程(3)YUV与RGBYUV4:2:2的工作原理四个像素:[Y0U0V0][Y1U1V1][Y2U2V2][Y3U3V3]存放的码流为:Y0U0Y1V1Y2U2Y3V3映射出:[Y0U0V1][Y1U0V1][Y2U2V3][Y3U2V3]从YUV解出RGBR=Y+1.14VG=Y-0.39U-0.58VB=Y+2.03U这说明从底层读出来的Camera数据是RawData…-20-Android&PervasiveComputingAndroid中Camera工作的具体过程(4)在哪里将这些YUV数据变成了JPEG,并将这些RawData撇去了?需要读源代码只能在这里这个显然在library层是依靠JNI进入的native部分-21-Android&PervasiveComputingAndroid对Camera的具体调用过程(5)UIAndroid.hardware.cameraApplicationsJavacallFrameworksLibrariesKernelCameraDriverlibandroid_runtime.solibcameraservice.solibui.soclientserviceJNIBinderIPClibcamera.soAndroid的Java层只是一个外壳packagesframeworks-22-Android&PervasiveComputingAndroid中Camera工作的具体过程(6)开始分析Camera的源代码这部分属于CameraHAL层,由下面目录中的源代码编译而成libcamer