当前位置:   article > 正文

Android拍摄并进行图像识别(一)_android开发相机识别

android开发相机识别

一、简介

最近在学习实现Android的拍照AI识别功能,主要通过调用手机系统的摄像机来完成拍照,并通过网络服务访问百度智慧云上的图像识别api来进行识图,最后将识图结果返回到app中。我把这个功能分成两个部分,分别是拍摄和识别,这篇文章讲的是拍摄部分。

二、程序流程图

(C:\Users\16695\AppData\Roaming\Typora\typora-user-images\image-20230104150644162.png)]

三、核心代码解析

1.主界面跳转到拍照界面
private void turnOnCamera() {
    //打开相机
    Intent intent = new Intent(MainActivity.this, CameraActivity.class);
    //从CameraActivity返回数据到MainActivity,CameraActivity中使用setResult设置要返回的值,其实是返回了图片的路径
    startActivityForResult(intent,TAKE_PHOTO_CODE);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
2.实现无触摸自动拍照
@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使用代码主动去调用控件的点击事件(模拟人手去触摸控件)
        }
    });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
public void takePhoto() {
    if (isClick) {
        isClick = false;
        mCameraSurfaceView.takePicture(mShutterCallback, rawPictureCallback, jpegPictureCallback);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

其中mCameraSurfaceView是CameraSurfaceView类的对象,CameraSurfaceView是自定义的类来调用Camera的功能,包括预览功能,拍照功能,快门回调等

(1)拍照功能:
public void takePicture(Camera.ShutterCallback mShutterCallback, Camera.PictureCallback rawPictureCallback, Camera.PictureCallback jpegPictureCallback) {
    mCamera.takePicture(mShutterCallback, rawPictureCallback, jpegPictureCallback);
    //mShutterCallback拍照回调函数
    //RAW图像就是CMOS或者CCD图像感应器将捕捉到的光源信号转化为数字信号的原始数据。
    //JPG图像是经过压缩后的图像数据
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
(2)预览功能:
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();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
3.保存照片并返回主界面
//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;

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
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();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

四、总结

​ 调用手机拍照这个不是很难,因为有现成的Camera类,我们只需要写一个CameraSurfaceView来调用相机的功能就可以了,然后在CameraActivity中通过CameraSurfaceView来调用拍照功能和预览功能就可以了;拍摄照片比较简单,而保存照片就要检查SD卡的状态来决定能否保存,然后要用到缓冲输出流来为文件输出提供缓冲功能,最终将数据稳定的传送到文件输出流上。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/566841
推荐阅读
相关标签
  

闽ICP备14008679号