Android(安卓)Camera图像处理学习
学习资料
- GcsSloop 安卓自定义View进阶-Matrix Camera
- 麻花儿wt的android camera 3d特效 详解与进阶
十分感谢GcsSloop
,直接去看他的博客学习,图文并茂
Android
中有2个Camera
,android.hardware.Camera
和android.graphics.Camera
,看包名就可以区分出两个Camera
的作用。hardware
硬件,是摄像头;graphics
,图像,用于图形处理。android.hardware.Camera
在5.0
后被废弃,由android.hardware.Camera2
代替,具体使用可以看看Android Camera2 拍照入门学习 : )
1. android.graphics.Camera
A camera instance can be used to compute 3D transformations and generate a matrix that can be applied, for instance, on a Canvas.
Camera
对象可以用来计算3D
变换,并将计算结果封装进一个Matrix
矩阵,之后便进行应用(ps:我这都啥破翻译)
Camera
可以用在画布上 。计算过程进行了封装,内部有一个Matrix
只有一个空的构造方法Camera()
Camera
既然可以用来做3D
三维变换,坐标系就和之前学习遇到的二维坐标系不同,是左手坐标系统,Y轴
在三维坐标系中是向上的,Z轴
是朝向屏幕里面的
Z轴
是朝里面的,屏幕像一个窗口,我们看到的是窗口外面的物体投射到窗口上的二维镜像。Camera
实际上就像我们的眼睛,眼睛看到的是物体投射到窗口上的图形,其实这里就有3个要素,一是物体,二是窗子,三是眼睛,也就是物体,屏幕和Camera
。最终呈现在用户面前的是屏幕上的图形。影响物体投射到屏幕上的效果,可以移动物体(Matrix
),也可以移动眼睛(setLocation()
方法)
以上从麻花儿wt的android camera 3d特效 详解与进阶摘抄
Camera位置在一个虚拟的3D的立体空间中,由于我们无法直接用眼睛去观察这一个空间,所以要借助摄像机采集信息,制成2D影像供我们观察。简单来说,摄像机就是我们观察虚拟3D空间的眼睛。
Android 上面观察View的摄像机默认位置在屏幕左上角,而且是距屏幕有一段距离的,假设灰色部分是手机屏幕,白色是上面的一个View,摄像机位置看起来大致就是下面这样子的(为了更好的展示摄像机的位置,做了一个空间转换效果的动图)。
Camera
默认距离为-8
,1
为72像素
,在坐标系中(0,0,-576)
以上从GcsSloop 安卓自定义View进阶-Matrix Camera摘抄
对于一个像素点的矩阵来说
一个像素点矩阵1
为Camera
在Z轴
的默认值,比1
大,代表相对于默认位置,将屏幕进行拉远。远小近大,值越大就越远,投射到Camera
上的图像也就也小
2. 方法
Camera
中方法并不算多
原始图像只是将Bitmap
宽高缩小为1/2
后,绘制在了画布上
2.1 translate(float x, float y, float z)
方法的名字和参数都比较容易理解,这个方法可以理解为移动了物体,但z
这个值,会影响x,y
的值。
例如mCamera.translate(100,0,100)
,x
的值为100,但最终显示效果,图像右移的距离并没有100。z
值导致图像缩放,移动距离也进行了缩放
Y轴
是向上的,mCamera.translate(0,30,0)
与mMatrix.translate(0,-30)
效果是一样的
2.2 rotate(float x, float y, float z)
这个方法是rotateX(float x),rotateY(float y),rotateZ(float z)
的综合
以默认点左上角为中心绕值不为0
的轴顺时针进行旋转
例如rotate(30,0,0)
,就是以左上角为中心,绕X轴
顺时针旋转30°
x
的值为角度,0°到360°
简单使用:
/** * 初始化 */ private void init() { mCamera = new Camera(); mMatrix = new Matrix(); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; options.inPreferredConfig = Bitmap.Config.RGB_565; mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test, options); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mCamera.save(); mCamera.rotate(180,0,0); mCamera.getMatrix(mMatrix); mCamera.restore(); mMatrix.postTranslate(0,500); canvas.drawBitmap(mBitmap,mMatrix, null); }
以控件左上角为旋转中心,绕x轴旋转180° mMatrix.postTranslate(0,500)
,矩阵后乘,由于图片默认以左上角为旋转中心,绕着x轴
旋转180°
,图片已经超出了屏幕,使用后乘平移,将图片再移动到屏幕范围内。不可以setTanslate()
,因为set
方法会将原先的矩阵的值清空,成为初始矩阵
其他同理
2.3 setLocation(float x, float y, float z)
设置相机的位置,默认为-8
简单修改代码,修改相机的位置
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mCamera.save(); mCamera.setLocation(0,0,-30);//设置相机位置 mCamera.rotate(0,30,0); mCamera.getMatrix(mMatrix); mCamera.restore(); mMatrix.postTranslate(0,500); canvas.drawBitmap(mBitmap,mMatrix, null); }
修改相机位置后 Y轴
方向是向屏幕里的,所以-30
比-8
要离物体远,这样旋转的最终效果就会减轻,根据生活经验,手机拍照时,手机距离拍摄物的远近,物体进行同样角度的改变,照片的效果并不完全一样。但Z轴
的值并不会影响平移操作
3.结合动画,形成简单的3D效果
代码是从GcsSloop 安卓自定义View进阶-Matrix Camera学到,里面涉及到的优化原理讲的很好
矩阵值的影响动画代码:
public class Rotate3DAnimation extends Animation { private final float mFromDegrees; private final float mToDegrees; private final float mCenterX; private final float mCenterY; private final float mDepthZ; private final boolean mReverse; private Camera mCamera; float scale = 1; // 像素密度 /** * 创建一个绕y轴旋转的3D动画效果,旋转过程中具有深度调节,可以指定旋转中心。 * @param context <------- 添加上下文,为获取像素密度准备 * @param fromDegrees 起始时角度 * @param toDegrees 结束时角度 * @param centerX 旋转中心x坐标 * @param centerY 旋转中心y坐标 * @param depthZ 最远到达的z轴坐标 * @param reverse true 表示由从0到depthZ,false相反 */ public Rotate3DAnimation(Context context, float fromDegrees, float toDegrees, float centerX, float centerY, float depthZ, boolean reverse) { mFromDegrees = fromDegrees; mToDegrees = toDegrees; mCenterX = centerX; mCenterY = centerY; mDepthZ = depthZ; mReverse = reverse; // 像素密度 scale = context.getResources().getDisplayMetrics().density; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { final float fromDegrees = mFromDegrees; float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime); final float centerX = mCenterX; final float centerY = mCenterY; final Camera camera = mCamera; final Matrix matrix = t.getMatrix(); camera.save(); // 调节深度 if (mReverse) { camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime); } else { camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime)); } // 绕y轴旋转 camera.rotateY(degrees); camera.getMatrix(matrix); camera.restore(); // 修正失真,主要修改 MPERSP_0 和 MPERSP_1 float[] mValues = new float[9]; matrix.getValues(mValues); //获取数值 mValues[6] = mValues[6]/scale; //数值修正 mValues[7] = mValues[7]/scale; //数值修正 matrix.setValues(mValues); //重新赋值 // 调节中心点 matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); }}
Activity
代码:
public class CameraGActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera_g); initView(); } private void initView() { ImageView iv = (ImageView) findViewById(R.id.iv_camera_g_activity); iv.setImageResource(R.drawable.test); iv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 计算中心点(这里是使用view的中心作为旋转的中心点) final float centerX = v.getWidth() / 2.0f; final float centerY = v.getHeight() / 2.0f; //括号内参数分别为(上下文,开始角度,结束角度,x轴中心点,y轴中心点,深度,是否扭曲) final Rotate3DAnimation rotation = new Rotate3DAnimation(CameraGActivity.this, 0, 360, centerX, centerY, 0f, true); rotation.setDuration(3000); rotation.setFillAfter(true); rotation.setInterpolator(new LinearInterpolator()); v.startAnimation(rotation); } }); }}
围绕图片中心旋转 优化就是修正失真,主要修改 MPERSP_0
和 MPERSP_1
4. 最后
本篇内容的学习,是最近学习过程中,效率最低的,Camera
与物体,屏幕三者的关系没有搞清楚,一开始搜到的学习博客,感觉有错误,质量不是很高。
强烈推荐学习GcsSloop的系列博客,感觉质量都很高,真正的图文并茂
本人很菜,写的很水,有错误请指出
共勉 : )
更多相关文章
- 【Android(安卓)进阶】Iconfont 图标的使用以及自定义
- Android(安卓)UI开发第十一篇――右上角带个泡泡
- Android之利用android:indeterminateDrawable来实现ProgressBar
- Android进阶之抢购倒计时功能
- Android属性动画2-----自定义属性动画
- Android音频进阶
- Android自定义组件系列【7】——进阶实践(4)
- android UI进阶之自定义组合控件
- [sg] Android(安卓)4.4 屏幕旋转的两种方式