安卓开发中经常有需要使用摄像头的应用场景,对于初次接触的同学摄像头的方向是一个比较难弄清楚的概念,开发时很容易处理不当,本文将详述该部分内容帮助理解。

一、摄像头捕获的图像

先看一个简单的场景,打开手机的后置摄像头拍摄,摄像头捕获的图像帧数据可通过Camera.PreviewCallback回调中获取,也就是摄像头的输出数据,

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

这里我们先忽略屏幕上的预览,只关注摄像头的输出。如果把它保存为图片或直接显示出来,可以看到图像和原始画面相比逆时针旋转了90度。

而我们如果同样使用iPhone手机拍摄,输出的结果是一个正向的图片。

二、摄像头的正向

为什么输出的图像相比原始画面旋转了90度?因为设备的摄像头存在一个“正向角度”,什么是摄像头的正向?

通俗一点讲,设备相当于人的身体,眼睛相当于摄像头,眼睛把接收到的画面反馈给大脑处理,相当于摄像头把接收到的数据给应用程序处理。人眼能判断出我们头顶向上的方向是我们视觉上的正向,而后置摄像头判断的正向并不是手机物理屏幕向上的方向,而是物理屏幕右侧的方向。我们想象一下,如果人眼是这个摄像头,它认为右侧才是我们的视觉正向,那我们看到的东西是不是都是旋转90度的?这样就比较好理解了。

上图是手机在竖直和水平方向摄像头“看”到的画面。

固定设备,指定的摄像头,正向角度固定的(0/90/180/270),和屏幕旋转、横竖屏切换无关,一般都在屏幕的右侧(但不排除某些厂商修改成别的)。

这个角度在代码中可通过Camera.CameraInfo的orientation获取,官方文档也有解释:

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.

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.

意思就是输出的图片需要顺时针旋转多少度,才能在自然方向上正确显示。这里的自然方向就是以标题栏左上角为原点的屏幕渲染坐标系,图片旋转后,把它放到渲染坐标系中,能和原始画面一样正常显示。

上图红点代表了图片的坐标原点,蓝点则代表屏幕渲染坐标的原点。只有做了旋转处理,渲染到屏幕上的预览图像才是正确的(和原始画面一样),而这个旋转的角度,就是orientation的值。

注意,正向始终在物理屏幕的右侧(想象音量键那边有一个正向箭头),orientation就等于从摄像头的角度(想象成人眼)看,从物理设备的正上方向(想象听筒位置有个箭头),需要顺时针旋转多少度才能到正向的箭头。所以,根据这个想象一下前后摄像头的区别,这个值后置摄像头是90,前置摄像头是270。

iPhone的摄像头正向就是物理设备的正上方,对应的正向角度是0,所以输出的图像是正向的。

三、如何正确地预览图像

其实不预览应用程序也能正确获取到摄像头的输入,但是一般应用打开摄像头后都会在屏幕上显示当前拍摄到的画面,这是用户的基本的使用体验。正确的预览图像就是让摄像头输出的图像能够正确的在屏幕上显示给用户。

如上节所述,摄像头采集到的图像按照orientation旋转和渲染坐标系对齐即可,这样就能正确显示图像了。不过这是在屏幕方向锁定的情况下,就是渲染坐标系始终在物理屏幕的左上方。

如果我们打开了设备陀螺仪(锁屏),屏幕可以在四个方向上切换,对应渲染的坐标原点(蓝点)会在物理屏幕的四个角上切换。

切换方向的角度可以通过activity.getWindowManager().getDefaultDisplay().getRotation();获取,和前后摄像头无关:

屏幕切换的角度值

这个角度可以理解为,以物理设备左上角为原点的渲染坐标系(听筒左边的角点),需要顺时针旋转多少度,才能变成当前的渲染坐标系。打开陀螺仪后,无论手机怎么旋转,当前的渲染坐标系永远以绝对左上角为原点(视觉左上方角点)。这个角度恰好和物理旋转的角度相反。

我们只要根据当前的切换角度+摄像头正向角度正确地设置显示角度就行了,官方文档也有现成的适配代码,详见setDisplayOrientation。

注意,setDisplayOrientation只会对预览显示的图像有影响,并不会影响onPreviewFrame回调的数据。

public static void setCameraDisplayOrientation(Activity activity,

int cameraId, android.hardware.Camera camera) {

android.hardware.Camera.CameraInfo info =

new android.hardware.Camera.CameraInfo();

android.hardware.Camera.getCameraInfo(cameraId, info);

int rotation = activity.getWindowManager().getDefaultDisplay()

.getRotation();

int degrees = 0;

switch (rotation) {

case Surface.ROTATION_0: degrees = 0; break;

case Surface.ROTATION_90: degrees = 90; break;

case Surface.ROTATION_180: degrees = 180; break;

case Surface.ROTATION_270: degrees = 270; break;

}

int result;

if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {

result = (info.orientation + degrees) % 360;

result = (360 - result) % 360; // compensate the mirror

} else { // back-facing

result = (info.orientation - degrees + 360) % 360;

}

camera.setDisplayOrientation(result);

}

如果还不理解这段代码的意思,看下这张图就明白了:

蓝点是渲染的坐标原点,红点是输出图片的原点。每一次旋转图片的原点就会变换到绝对位置的左上角,setDisplayOrientation要设置的值就是图像要顺时针旋转的角度,使图片能在渲染坐标系中正确显示。从图中也能看出来,它就是第二列的箭头需要顺时针旋转到第一列箭头的角度。

android摄像头方向与屏方向,Android开发中关于摄像头方向的理解相关推荐

  1. 游戏陪玩app源码开发中,摄像头的调用及视频处理

    摄像头是游戏陪玩app源码进行视频连麦时的重要移动设备之一,在开发时,我们需要实现游戏陪玩app源码对摄像头的调用权限,这就涉及到相关接口的开发了,不过今天我们主要来了解一下在游戏陪玩app源码开发中 ...

  2. android写代码截屏微信,android 模仿微信头像裁剪

    android 在android开发中经常会碰到修改头像的功能需求, 而在修改头像>中最难的部分就是在头像的裁剪功能.虽说网上一大堆裁剪的例子,但最重要的是要理解里面的实现原理,这样以后自己改起 ...

  3. android启动画面白屏,解决Android APP启动出现白屏的问题

    一.前言 Android开发者都会有这样的体会吧!自己开发的APP,在启动APP的时候,会出现一段时间白屏,然后才会显示APP的界面.其实这段时间的出现,是APP在启动时,需要初始化一些数据,然后才会 ...

  4. android怎么监听多点触摸_Android开发中多点触摸的实现方法

    Android多点触控需要LCD驱动和程序设计支持,其实我们只要采用电容屏触摸手机的技术即可,接下来,就让爱站技术频道小编来讲解Android开发中多点触摸的实现方法吧! 多点触摸技术在实际开发过程中 ...

  5. android 监听锁屏 权限,Android中监听锁屏变化和防止锁屏

    Android app中可能存在某些可视化耗时操作,需要防止锁屏. 一.监听锁屏 添加权限 首先来看如何监听锁屏,使用BroadcastReceivercaset来监听 1.锁屏监听 public c ...

  6. 上传图片方向不对 php,如何解决IOS中html5上传图片方向问题?

    这篇文章主要介绍了IOS中html5上传图片方向问题解决方法的相关资料,需要的朋友可以参考下 用html5编写图片裁切上传,在iphone手机上可能会遇到图片方向错误问题,在此把解决方法和大家分享一下 ...

  7. android 8.0 录屏命令,Android前置摄像头录制的视频介于7.5和8.0之间 – setVideoFrameRate不起作用 – 三星Galaxy S2...

    我正在尝试使用前置摄像头录制视频,以下是代码段,我将setVideoFrameRate设置为29,但是录制的视频的fps为7.5到8.我需要录制vidio的视频fps 29. recorder.set ...

  8. android实现自动横竖屏切换,android 中实现横竖屏切换【原创】

    我们在使用android手机的时候,发现一些应用有横竖屏切换的功能,一般实现有以下几种方法: 一.设置 1.通过XML设置横竖屏切换 在项目的 AndroidManifest.xml中找到你所指定的a ...

  9. android 让app全屏显示,Android app设置全屏模式

    Android中,为APP设置全屏模式,主要有如下几种方式: 在manifest中设置 在项目中找到AndroidManifest.xml配置文件,找到Activity所在的节点,添加theme. p ...

最新文章

  1. 【c语言】蓝桥杯算法提高 7-1用宏求球的体积
  2. Struts2与Webwork2的区别
  3. centos 调整系统时间
  4. Java并发编程之ConcurrentHashMap
  5. 【CV】综述:基于深度学习的视觉跟踪方法进展
  6. P5895-[IOI2013]dreaming梦想【树的直径,结论】
  7. Struts2学习笔记《二》
  8. REVERSE-PRACTICE-JarvisOJ-4
  9. 基于PyQt的扫雷游戏实现_下篇
  10. 拓端tecdat|R语言Black Scholes和Cox-Ross-Rubinstein期权定价模型案例
  11. 批量更改图片文件的格式有什么方法?
  12. 概率论第一章习题答案以及解析
  13. CPU的内部架构和工作原理(简介)
  14. 山东科技大计算机与软件工程,山东科技大学(专业学位)软件工程考研难吗
  15. FLStudio水果最新版本V21支持中文语言
  16. 一份Yann LeCun等16个顶级数据科学家给新人的建议
  17. anchor free和anchor based的区别
  18. 特征工程之One-Hot编码、label-encoding、自定义编码
  19. mui 写出Tab标签可滑动可点击的效果(下划线效果)
  20. 武汉市科技重大专项项目榜单申报条件、流程时间

热门文章

  1. idea 起项目乱七八糟报错
  2. CobaltStrike上线Linux主机(CrossC2)
  3. x265笔记_4_CompressCTU源码分析
  4. MATLAB中画曲线网格
  5. web of science 校外访问方法
  6. JAVA毕业设计健康生活运动咨询系统计算机源码+lw文档+系统+调试部署+数据库
  7. 51CTO首届卡拉OK大赛:我唱,为欢聚而歌
  8. cocos2d 高仿doodle jump 无源代码
  9. 【机械】基于广义Hoek-Brown实现应变软化岩体GRC曲线及围岩位移应力塑性区绘制附matlab代码
  10. codeforces 577B Modulo Sum