赞
踩
最近在学习实现Android的拍照AI识别功能,主要通过调用手机系统的摄像机来完成拍照,并通过网络服务访问百度智慧云上的图像识别api来进行识图,最后将识图结果返回到app中。我把这个功能分成两个部分,分别是拍摄和识别,这篇文章讲的是拍摄部分。
private void turnOnCamera() {
//打开相机
Intent intent = new Intent(MainActivity.this, CameraActivity.class);
//从CameraActivity返回数据到MainActivity,CameraActivity中使用setResult设置要返回的值,其实是返回了图片的路径
startActivityForResult(intent,TAKE_PHOTO_CODE);
}
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.camera); ImageView img_take_photo = (ImageView) findViewById(R.id.img_take_photo); mCameraSurfaceView = (CameraSurfaceView) findViewById(R.id.sv_camera); img_take_photo.setOnClickListener(new View.OnClickListener() { //设置点击事件 @Override public void onClick(View v) { takePhoto(); } }); //模拟人手去点击按钮,相当于一打开拍摄页面立刻调用控件的点击事件 img_take_photo.post(new Runnable() { @Override public void run() { img_take_photo.performClick(); //performClick使用代码主动去调用控件的点击事件(模拟人手去触摸控件) } }); }
public void takePhoto() {
if (isClick) {
isClick = false;
mCameraSurfaceView.takePicture(mShutterCallback, rawPictureCallback, jpegPictureCallback);
}
}
其中mCameraSurfaceView是CameraSurfaceView类的对象,CameraSurfaceView是自定义的类来调用Camera的功能,包括预览功能,拍照功能,快门回调等
public void takePicture(Camera.ShutterCallback mShutterCallback, Camera.PictureCallback rawPictureCallback, Camera.PictureCallback jpegPictureCallback) {
mCamera.takePicture(mShutterCallback, rawPictureCallback, jpegPictureCallback);
//mShutterCallback拍照回调函数
//RAW图像就是CMOS或者CCD图像感应器将捕捉到的光源信号转化为数字信号的原始数据。
//JPG图像是经过压缩后的图像数据
}
public void startPreview() { Log.d("Camera","进入StartPreview()"); mCamera.startPreview(); } @Override public void surfaceCreated(SurfaceHolder holder) { if (mCamera == null) { mCamera = Camera.open(); } mCamera.setDisplayOrientation(ORIENTATION); //设置预览图像的旋转方向 try { mCamera.setPreviewDisplay(holder); //为Preview分配内存 } catch (IOException e) { e.printStackTrace(); } } //设置预览图片尺寸 @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Camera.Parameters parameters = mCamera.getParameters();// 获取mCamera的参数对象 Camera.Size largestSize = getBestSupportedSize(parameters .getSupportedPreviewSizes()); parameters.setPreviewSize(largestSize.width, largestSize.height);// 设置预览图片尺寸 largestSize = getBestSupportedSize(parameters .getSupportedPictureSizes());// 设置捕捉图片尺寸 parameters.setPictureSize(largestSize.width, largestSize.height); //对 PreparedStatement 的参数赋值,PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程 mCamera.setParameters(parameters); mCamera.startPreview(); }
//jpg的压缩图像回调并保存数据
private Camera.PictureCallback jpegPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
mCameraSurfaceView.startPreview();
saveFile(data);
Toast.makeText(CameraActivity.this, "拍照成功", Toast.LENGTH_SHORT).show();
isClick = true;
}
public void saveFile(byte[] data) { SimpleDateFormat timeStampFormat = new SimpleDateFormat("HH_mm_ss"); File file = null; //用时间格式来命名照片 String filename = timeStampFormat.format(new Date()); //创建File对象 FileOutputStream outputStream = null; //判断SD卡状态,状态为MEDIA_MOUNTED时/mnt/sdcard目录才是可读可写,并且可以创建目录及文件 if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Log.d("CameraData","SD卡不可用"); } try { File dir = new File(getExternalFilesDir(null).getPath()+"/takePhoto"); if (!dir.exists()) { //没有文件路径 dir.mkdir(); Log.d("CameraData", "文件路径创建成功"); } file = new File(dir+ "/"+ filename + ".jpg"); if (!file.exists()) { //不存在该图片 file.createNewFile(); Log.d("CameraData", "文件创建成功"); } outputStream = new FileOutputStream(file); Log.d("CameraData","创建字节流成功"); //BufferedOutputStream缓冲输出流为文件输出流提供缓冲功能 BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream); //把data的数据写到bufferedOutputStream里面去 bufferedOutputStream.write(data, 0, data.length); } catch (Exception e) { e.printStackTrace(); } finally { try { if(outputStream != null)outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } //带着照片的绝对路径返回主界面 Intent img = new Intent(); img.putExtra("photo", file.getAbsolutePath()); this.setResult(-1,img); finish(); }
调用手机拍照这个不是很难,因为有现成的Camera类,我们只需要写一个CameraSurfaceView来调用相机的功能就可以了,然后在CameraActivity中通过CameraSurfaceView来调用拍照功能和预览功能就可以了;拍摄照片比较简单,而保存照片就要检查SD卡的状态来决定能否保存,然后要用到缓冲输出流来为文件输出提供缓冲功能,最终将数据稳定的传送到文件输出流上。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。