创建的空 OpenCV 安卓应用程序以支持摄像头

在本节中,我们将扩展上一节中创建的空 OpenCV 应用程序以支持摄像头。我们将获取摄像头帧并将其显示在屏幕上。

告诉系统我们需要相机权限。将以下代码添加到文件MyApplication/app/src/main/AndroidManifest.xml

XML 复制代码
    <uses-permission android:name="android.permission.CAMERA"/>
 
    <uses-feature android:name="android.hardware.camera" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
  1. 转到activity_main.xml布局并删除带有文本"Hello World!"的 TextView

TextView这也可以在代码或拆分模式下通过从 XML 文件中删除块来完成。

  1. 将相机视图添加到布局中:

    在布局描述中添加方案:

xmlns:opencv = "http://schemas.android.com/apk/res-auto"

TextView用小部件替换org.opencv.android.JavaCameraView

XML 复制代码
    <org.opencv.android.JavaCameraView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="gone"
        android:id="@+id/tutorial1_activity_java_surface_view"
        opencv:show_fps="true"
        opencv:camera_id="any" />
  1. 如果你收到布局警告,请用for和properties替换fill_parentmatch_parent``android:layout_width``android:layout_height

您将获得如下代码:

XML 复制代码
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:opencv="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
 
    <!-- [camera_view] -->
    <org.opencv.android.JavaCameraView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="gone"
        android:id="@+id/tutorial1_activity_java_surface_view"
        opencv:show_fps="true"
        opencv:camera_id="any" />
    <!-- [camera_view] -->
 
</FrameLayout>
  1. 从 继承主类。CameraActivity 实现相机权限请求和org.opencv.android.CameraActivityCV 应用程序所需的一些其他实用程序。我们想要重写的方法包括onCreateonDestroy、和onPause``onResume``getCameraViewList
  2. 实现接口org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2 onCameraFrame方法应该返回Mat带有内容的对象以供渲染。示例仅返回相机帧以供预览:return inputFrame.rgba();
  3. 分配org.opencv.android.CameraBridgeViewBase对象:
    • 它应该在应用程序启动时创建(onCreate方法),并且该类应该设置为监听器
    • 在暂停/恢复(onPauseonResume方法)时应该禁用/启用它
    • 应在应用程序完成时禁用(onDestroy方法)
    • 应归还getCameraViewList
  4. 您可以选择禁止手机调暗屏幕或锁定:
java 复制代码
 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

最终的源码:

java 复制代码
package org.opencv.samples.tutorial1;
 
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
 
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.Toast;
 
import java.util.Collections;
import java.util.List;
 
public class Tutorial1Activity extends CameraActivity implements CvCameraViewListener2 {
    private static final String TAG = "OCVSample::Activity";
 
    private CameraBridgeViewBase mOpenCvCameraView;
 
    public Tutorial1Activity() {
        Log.i(TAG, "Instantiated new " + this.getClass());
    }
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
 
        if (OpenCVLoader.initLocal()) {
            Log.i(TAG, "OpenCV loaded successfully");
        } else {
            Log.e(TAG, "OpenCV initialization failed!");
            (Toast.makeText(this, "OpenCV initialization failed!", Toast.LENGTH_LONG)).show();
            return;
        }
 
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
 
        setContentView(R.layout.tutorial1_surface_view);
 
        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);
 
        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
 
        mOpenCvCameraView.setCvCameraViewListener(this);
    }
 
    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }
 
    @Override
    public void onResume()
    {
        super.onResume();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.enableView();
    }
 
    @Override
    protected List<? extends CameraBridgeViewBase> getCameraViewList() {
        return Collections.singletonList(mOpenCvCameraView);
    }
 
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }
 
    @Override
    public void onCameraViewStarted(int width, int height) {
    }
 
    @Override
    public void onCameraViewStopped() {
    }
 
    @Override
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        return inputFrame.rgba();
    }
}

就是这样!现在您可以在设备上运行代码来检查它。

记录一下最重要的步骤

每个带有 UI 的 Android 应用程序都必须实现 Activity 和 View。首先,我们创建空白活动和默认视图布局。最简单的以 OpenCV 为中心的应用程序必须执行 OpenCV 初始化,创建一个视图来显示来自摄像头的预览,并实现CvCameraViewListener2接口以从摄像头获取帧并对其进行处理。

首先,我们使用 XML 布局创建应用程序视图。我们的布局仅包含一个类的全屏组件org.opencv.android.JavaCameraView。此 OpenCV 类继承自CameraBridgeViewBase扩展类SurfaceView,并在底层使用标准 Android 相机 API。

CvCameraViewListener2接口允许您在从相机抓取帧之后和在屏幕上渲染之前添加一些处理步骤。最重要的方法是onCameraFrame。这是一个回调函数,在从相机检索帧时调用。它期望该onCameraFrame函数返回将在屏幕上绘制的 RGBA 帧。

回调将相机中的帧作为类对象传递给我们的类CvCameraViewFrame。此对象具有rgba()gray()方法,可让用户获取彩色或单通道灰度帧作为Mat类对象。

笔记

不要保存或使用回调CvCameraViewFrame之外的对象onCameraFrame。此对象没有自己的状态,并且其在回调之外的行为不可预测!

相关推荐
Lethehong40 分钟前
昇腾Atlas 800T平台下Qwen-14B大语言模型的SGLang适配与性能实测
人工智能·语言模型·sglang·昇腾npu
杜子不疼.41 分钟前
Spring AI 与向量数据库:构建企业级 RAG 智能问答系统
数据库·人工智能·spring
ayingmeizi16343 分钟前
AI CRM赋能全链路数字化如何重塑医械企业渠道竞争力?
人工智能
————A1 小时前
从 RAG 召回失败到故障链推理
人工智能·rag
Chase_______2 小时前
AI提效指南:Nano Banana 生成精美PPT与漫画
人工智能·powerpoint
雨大王5122 小时前
汽车产业供应链优化的可行策略及案例分析
人工智能·机器学习
梁辰兴2 小时前
三星自研GPU剑指AI芯片霸权,2027年能否撼动英伟达?
人工智能·gpu·芯片·电子·ai芯片·三星·梁辰兴
吴佳浩8 小时前
Python入门指南(七) - YOLO检测API进阶实战
人工智能·后端·python
tap.AI8 小时前
RAG系列(二)数据准备与向量索引
开发语言·人工智能
老蒋新思维9 小时前
知识IP的长期主义:当AI成为跨越增长曲线的“第二曲线引擎”|创客匠人
大数据·人工智能·tcp/ip·机器学习·创始人ip·创客匠人·知识变现