Android的摄像头操作随笔记

来源:互联网 发布:马桶推荐 知乎 编辑:程序博客网 时间:2024/06/05 05:11

最近项目需要用到很多的摄像头,比如自己写一个照相机、人脸识别、图片识别等等。都要使用摄像头,变态的还有,截取视频流的某一帧。

好了,主题了吧。这里只有android.hardware.Camera包下的笔记和android.view.surfaceView的笔记。


新手看一下,大神绕道!

一、先总体的记一下

我们使用android的拍照等功能,本来是可以调用系统自带的,一般都是隐式的Intent实现的。但是,老板的诸多要求,系统自带操作不方便,于是我们就被逼着上了梁山,使用surfaceView自己画一个。


首先,我们需要记住就是摄像头的预览需要载体,那么这个载体是什么?android提供的载体就是surfaceView。

在这里,我简单的讲一下surfaceView,它是专门用来绘制的,用来呈现常规控件无法呈现内容的或者需要加入很多的个人色彩的东西的时候。

使用它和使用Button基本一样的,布局文件加一个,声明ID。但是,它和Button的区别在于,我们需要为它设置一个回调android.view.SurfaceHolder.Callback。

记住,这是一个接口(interface),里面有三个方法,需要实现。执行的顺序是:surfaceCreated()--->surfaceChanged()----->surfaceDestoryed()。

如果英语可以的人,一看就是知道是什么意思。具体的代码这样实现的:

//声明

private SurfaceView surfaceview;
private SurfaceHolder surfaceholder;


//初始化

surfaceview = (SurfaceView) findViewById(R.id.mSurfaceView);
surfaceholder = surfaceview.getHolder();
surfaceholder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceholder.addCallback(MainActivity.this);

注意:最后一句话就是用来添加回调的。

二、应该进入Camera的主题了。

如果要使用android的摄像头它属于硬件设备。看看包名android.hardware.Camera,所以我们需要加入几个权限:

<uses-feature android:name="android.hardware.camera" />
  <uses-feature android:name="android.hardware.camera.autofocus"  android:required="false" />
        <uses-permission android:name="android.permission.CAMERA" />

对于Camera而言,我们需要知道几点:

1、对于一个手机而言,它一般都有前置和后置摄像头

· 2、Camera获得对象的方式,不是通过new关键字,也不通过单例模式,它是通过调用他自己的类方法open(int)传入的是前置或者后置摄像头的ID

3、接着第二点,我们还需要知道CameraInfo类。android.hardware.Camera.CameraInfo是它的包名。里面封装了许多常量,有两个记一下:

CameraInfo.CAMERA_FACING_FRONT=======前置摄像头

CameraInfo.CAMERA_FACING_BACK========后者摄像头

4、我们自己调用摄像头就是为了添加一些个性化的参数,现在就到了设置参数的时候了,android.hardware.Camera.Parameters类相当于一个JavaBean

里面封装了很多的私有属性,但是可以通过Set和Get方法去设置或者得到参数。里面有几个参数需要记一下:

Parameters params = mCamera.getParameters();//得到对象

params.setPreviewFormat(ImageFormat.NV21);//设置预览视频流的格式

params.setPreviewSize(480,640);//设置预览的大小

parameters.setPictureSize(320, 240);// 设置分辨率(主要是在图片识别的时候,高分辨需要处理的点多计算量太大)

mCamera.setParameters(params);//把上面的数据都提交,使它有效果

mCamera.setDisplayOrientation(90);//设置预览的时候旋转90°,主要是因为有的设备它会自己旋转,很别扭(但是拍出来的照片还是旋转的)

5、这些东西都准备好了,我们就可以开始预览了。

mCamera.startPreview();

三、到了最后的,从视频流中截取某一帧。

我们截取某一帧,并且对这一帧进行检测。比如人脸、书本等等。然后,接下来的工作就简单了。

mCamera.setPreviewCallback(new PreviewCallback() {

@Override
public void onPreviewFrame(byte[] data, Camera camera) {

}
});
 //里面的data 字节数组,就是我们主要处理的数据


四、我还可以拍照,然后对这张图进行相应的图片变化

camera.takePicture(null, null, mPictureCallback);

public Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
if (camera != null) {
}
}
};
//同样也是操作byte数组


五、我自己写几个对byte数组操作的方法,我就直接贴出来了。不解释了。

/**
* 将byte保存在sd卡中

* @param data
* @throws IOException
*/
public static String saveByteToSDCard(byte[] data, String name)
throws IOException {
File fileFolder = new File(Environment.getExternalStorageDirectory()
+ "/Test/");
if (!fileFolder.exists()) { // 如果目录不存在,则创建一个名为"finger"的目录
fileFolder.mkdir();
}
File jpgFile = new File(fileFolder, name);
FileOutputStream outputStream = new FileOutputStream(jpgFile); // 文件输出流
outputStream.write(data); // 写入sd卡中
outputStream.close(); // 关闭输出流
if (jpgFile.exists()) {
return jpgFile.getAbsolutePath();
}
return "";
}


// android灰度算法
// 算法一:GRAY = (max(red, green, blue) + min(red,green, blue))/2
// //
// 算法二:GRAY = (red + green + blue)/3 //
// 算法三:GRAY= red*0.3 + green*0.59 + blue*0.11 //
/**
* @param bitmap

* @return
*/
public int[] grayTo8Array(byte[] data) {

BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap  mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length,options);

int width = mBitmap.getWidth();
int height = mBitmap.getHeight();
int[] pix = new int[width * height];
mBitmap.getPixels(pix, 0, width, 0, 0, width, height);//
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int color = pix[width * i + j];//
int red = ((color & 0x00FF0000) >> 16);//
int green = ((color & 0x0000FF00) >> 8);//
int blue = color & 0x000000FF;//
color = (int) (red * 0.3 + green * 0.59 + blue * 0.11);//
pix[width * i + j] = color;
}
}
return pix;
}






















1 0