当前位置: 首页 > article >正文

Android 检测图片抓拍, 聚焦图片后自动完成拍照,未对准图片的提示请将摄像头对准要拍照的图片

在 Android 中实现检测图片抓拍并在聚焦图片后自动完成拍照,同时在未对准图片时给出提示,可以通过以下步骤实现:

一、权限设置

AndroidManifest.xml文件中添加相机权限和存储权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

二、布局设计

创建一个布局文件,包含用于显示相机预览的SurfaceView、提示信息的TextView和一个按钮用于手动触发拍照(可选)。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <SurfaceView
        android:id="@+id/cameraPreview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TextView
        android:id="@+id/tipTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="请将摄像头对准要拍照的图片"
        android:textSize="18sp" />

    <Button
        android:id="@+id/takePictureButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="手动拍照" />

</RelativeLayout>

三、相机预览与自动拍照逻辑

  1. 创建一个CameraActivity类来处理相机相关的操作:
import android.app.Activity;
import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.TextView;

import java.io.IOException;

public class CameraActivity extends Activity implements SurfaceHolder.Callback {

    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;
    private Camera camera;
    private TextView tipTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);

        surfaceView = findViewById(R.id.cameraPreview);
        tipTextView = findViewById(R.id.tipTextView);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);

        if (checkCameraHardware(this)) {
            if (checkSelfPermission(android.Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{android.Manifest.permission.CAMERA}, 100);
            } else {
                openCamera();
            }
        } else {
            Log.e("Camera", "设备没有相机");
        }
    }

    private boolean checkCameraHardware(Activity activity) {
        return activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
    }

    private void openCamera() {
        try {
            camera = Camera.open();
            setCameraDisplayOrientation(this, Camera.CameraInfo.CAMERA_FACING_BACK, camera);
            camera.setPreviewDisplay(surfaceHolder);
            camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        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;
        } else {
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            if (camera!= null) {
                camera.setPreviewDisplay(holder);
                camera.startPreview();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (holder.getSurface() == null) {
            return;
        }
        try {
            camera.stopPreview();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            camera.setPreviewDisplay(holder);
            camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (camera!= null) {
            camera.stopPreview();
            camera.release();
            camera = null;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 100 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            openCamera();
        }
    }

    // 自动拍照方法
    private void autoTakePicture() {
        if (camera!= null) {
            camera.autoFocus(new Camera.AutoFocusCallback() {
                @Override
                public void onAutoFocus(boolean success, Camera camera) {
                    if (success) {
                        camera.takePicture(null, null, new Camera.PictureCallback() {
                            @Override
                            public void onPictureTaken(byte[] data, Camera camera) {
                                // 保存图片逻辑
                                savePicture(data);
                            }
                        });
                    }
                }
            });
        }
    }

    private void savePicture(byte[] data) {
        // 保存图片到指定位置
        // 这里可以根据你的需求进行图片保存操作
    }
}

2.在surfaceCreated方法中添加一个定时器,定期检查相机是否聚焦完成,如果聚焦完成则自动拍照:

@Override
public void surfaceCreated(SurfaceHolder holder) {
    try {
        if (camera!= null) {
            camera.setPreviewDisplay(holder);
            camera.startPreview();

            // 添加定时器检查聚焦状态
            new Timer().scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    if (camera!= null && camera.getParameters().getFocusMode().equals(Camera.Parameters.FOCUS_MODE_AUTO)) {
                        camera.autoFocus(null);
                    }
                }
            }, 0, 1000);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3.在自动聚焦的回调方法中,如果聚焦成功则触发自动拍照。

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 100 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        openCamera();

        // 开启自动拍照
        autoTakePicture();
    }
}

四、图片对准检测与提示

  1. 使用图像识别算法或特定的特征检测技术来判断图片是否对准。一种简单的方法是检测图像中的特定颜色、形状或纹理,但这可能不够准确。更复杂的方法可以使用机器学习模型进行图像分类或目标检测,但这需要更多的计算资源和专业知识。

例如,可以使用 OpenCV 库来进行一些基本的图像分析:

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;

public class CameraActivity extends Activity implements SurfaceHolder.Callback {

    //... 其他代码

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                    Log.i("OpenCV", "OpenCV loaded successfully");
                    // 在这里可以进行 OpenCV 的初始化和图像分析
                    break;
                default:
                    super.onManagerConnected(status);
                    Log.e("OpenCV", "OpenCV initialization failed");
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);

        //... 其他初始化代码

        if (!OpenCVLoader.initDebug()) {
            Log.d("OpenCV", "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_4_0, this, mLoaderCallback);
        } else {
            Log.d("OpenCV", "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    // 检测图片是否对准的方法
    private boolean isPictureAligned() {
        // 这里进行图像分析判断是否对准
        return false;
    }
}

2.在定时器的任务中,除了检查聚焦状态,还可以检查图片是否对准。如果未对准,则显示提示信息;如果对准且聚焦完成,则自动拍照:

new Timer().scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        if (camera!= null && camera.getParameters().getFocusMode().equals(Camera.Parameters.FOCUS_MODE_AUTO)) {
            camera.autoFocus(null);

            boolean aligned = isPictureAligned();
            if (!aligned) {
                runOnUiThread(() -> tipTextView.setVisibility(View.VISIBLE));
            } else {
                runOnUiThread(() -> tipTextView.setVisibility(View.INVISIBLE));
            }
        }
    }
}, 0, 1000);

这样就可以在 Android 中实现检测图片抓拍,聚焦图片后自动完成拍照,并在未对准图片时给出提示。需要注意的是,图像检测的准确性取决于所使用的算法和技术,可能需要根据具体的应用场景进行调整和优化。同时,确保处理好权限请求和异常情况,以提供良好的用户体验。


http://www.kler.cn/a/317711.html

相关文章:

  • 基于微信小程序的公务员考试学习平台的设计与实现,LW+源码+讲解
  • Android 13 实现屏幕熄屏一段时候后关闭 Wi-Fi 和清空多任务列表
  • 计算机网络 (1)互联网的组成
  • 机器学习【激活函数】
  • 闯关leetcode——3178. Find the Child Who Has the Ball After K Seconds
  • 机器学习在医疗健康领域的应用
  • 红书 API 接口:笔记详情数据接口的接入与使用
  • IDEA 关闭自动补全功能(最新版本)
  • 【我的 PWN 学习手札】House of Botcake —— tcache key 绕过
  • 我从家庭提取的动态IP是独享的吗?
  • RK3568笔记六十二:使用V4L2读取摄像头并在LCD上显示
  • TypeScript-面向对象(接口、类、对象、泛型)
  • 1.5 计算机网络的性能指标
  • Git可视化工具和基础命令
  • vue3<script setup>中使用reactive包裹的对象被重新赋值失去响应式原因和解决方式
  • C#控件开发能够阅读的书籍
  • ESP8266+DHT11+Python制作一个物联网温湿度传感器
  • 基于C#+SQL Server2005(WinForm)图书管理系统
  • 多边形抠图 python
  • python爬虫案例——抓取链家租房信息
  • IPsec-Vpn
  • 6、论文阅读:水下图像增强基准数据集及其他数据集
  • 【Godot4.3】三角形类
  • lunar无第三方依赖的公历、农历、法定节假日...日历工具库
  • 什么是单例模式?
  • 用最新的C++技术,如何实现一个序列化工具库?