深入OpenCV Android应用开发

前言

OpenCV是Open Source Computer Vision library(开源的计算机视觉库)的缩写。它是使用最广泛的计算机视觉库。Opencv是计算机视觉领域常用的操作函数的集合,其自身由C/C++编写而成,同时也提供了对Python、Java以及任意JVM语言的封装。考虑到大部分Android应用是用C++/Java编写的,OpenCV也被移植为供开发者使用的SDK,以使他们开发的应用支持机器视觉。

一.Android平台部署OpenCV

1.下载地址:

OpenCV - Browse /opencv-android at SourceForge.netOpenCV - Browse /opencv-android/3.4.3 at SourceForge.net

 点击opencv-3.4.3-android-sdk.zip下载

 

2.解压opencv-3.4.3-android-sdk.zip文件

3.创建Android项目命名为FirstOpenCVApp

4.找到opencv解压的文件夹

opencv-3.4.3-android-sdk下的java文件夹下的project.properties文件

例如压缩文件解压到桌面:C:\Users\SW\Desktop\opencv-3.4.3-android-sdk\OpenCV-android-sdk\sdk\java\project.properties

利用记事本打开,删除两行代码如下所示

删除后如下图所示:

由于AndroidStudio版本为4.1不删除无法编译通过。

5.Android项目导入opencv模块

点击File->New->Import Module...

选择Source directory:选择解压之后的目录C:\Users\SW\Desktop\opencv-3.4.3-android-sdk\OpenCV-android-sdk\sdk\java,点击OK

等待编辑完成,修改模块openCVLibrary343下的清单文件,去掉android:minSdkVersion="8"

删除之后的清单文件如下图所示:

修改模块openCVLibrary343下的build.gradle文件如下图所示:

以Android项目FirstOneOpencvApp下的src下的build.gradle为参考,尽量保持一致

FirstOneOpencvApp下的src下的build.gradle如下图所示:

点击同步,等待项目同步完成。

点击Android项目FirstOneOpencvApp File->Project Structure app添加Module依赖选择openCVLibrary343

检查Android项目FirstOneOpencvApp下的app下的build.gradle dependencies如下图所示:

检查settings.gradle如下图所示:

等待项目编译完成

6.Android项目新建HomeActivity

File->New->Activity->Empty Activity

Activity Name为HomeActivity

布局文件activity_home内容如下图所示

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".HomeActivity">
    <Button

        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:id="@+id/bMean"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Mean Blur"></Button>
</androidx.constraintlayout.widget.ConstraintLayout>

HomeActivity内容如下所示:

package com.suoer.comeonhealth.firstoneopencvapp;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

public class HomeActivity extends AppCompatActivity {
    public static final int MEAN_BLUR=1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        Button bMean=findViewById(R.id.bMean);
        bMean.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i=new Intent(getApplicationContext(),MainActivity.class);
                i.putExtra("ACTION_MODE",MEAN_BLUR);
                startActivity(i);
            }
        });
    }
}

7.修改MainActivity

布局activity_main内容如下图所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <ImageView
        android:layout_weight="0.5"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/ivImage"></ImageView>
    <ImageView
        android:layout_weight="0.5"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/ivImageProcessed"></ImageView>


</LinearLayout>

资源文件下添加菜单

menu_main内容如下图所示:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_load_image"
    android:title="加载图片"
    android:orderInCategory="1"
    app:showAsAction="ifRoom"></item>
</menu>

MainActivity内容如下图所示:

package com.suoer.comeonhealth.firstoneopencvapp;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

import java.io.FileNotFoundException;
import java.io.InputStream;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private final int SELECT_PHOTO=1;
    private ImageView ivImage,ivImageProcessed;
    Mat src;
    static int ACTION_MODE=0;
    private BaseLoaderCallback mOpenCVCallBack=new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
           switch (status){
               case SUCCESS:
                   //在这里完成
                   break;
               default:
                   super.onManagerConnected(status);
                   break;
           }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ivImage=findViewById(R.id.ivImage);
        ivImageProcessed=findViewById(R.id.ivImageProcessed);
        Intent intent=getIntent();
        if(intent.hasExtra("ACTION_MODE")){
            ACTION_MODE=intent.getIntExtra("ACTION_MODE",0);
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION,this,mOpenCVCallBack);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main,menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        int id=item.getItemId();
        if(id==R.id.action_load_image){
            Intent photoPickerIntent=new Intent(Intent.ACTION_PICK);
            photoPickerIntent.setType("image/*");
            startActivityForResult(photoPickerIntent,SELECT_PHOTO);
            return true;

        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case SELECT_PHOTO:
                if(resultCode==RESULT_OK){
                    try{
                        //以位图载入图像,并将其转换为Mat以供处理的代码
                        final Uri imageUri=data.getData();
                        final InputStream imageStream=getContentResolver().openInputStream(imageUri);
                        final Bitmap selectedImage= BitmapFactory.decodeStream(imageStream);
                        src=new Mat(selectedImage.getHeight(),selectedImage.getWidth(), CvType.CV_8UC4);
                        Utils.bitmapToMat(selectedImage,src);
                        switch (ACTION_MODE){
                            case  HomeActivity.MEAN_BLUR:
                                Imgproc.blur(src,src,new Size(3,3));
                                break;

                        }
                        //将Mat转换为位图,以便在ImageView中显示
                        Bitmap processedImage=Bitmap.createBitmap(src.cols(),src.rows(),Bitmap.Config.ARGB_8888);
                        Utils.matToBitmap(src,processedImage);
                        ivImage.setImageBitmap(selectedImage);
                        ivImageProcessed.setImageBitmap(processedImage);
                    }catch (FileNotFoundException e){
                        e.printStackTrace();
                    }
                }
                break;


        }
    }

}

8.查看手机设备的cpu架构

AndroidStudio连接手机

运行cmd.exe 输入命令:adb shell getprop ro.product.cpu.abi点击回车

arm64-v8a就是连接手机的cpu架构

找到opencv解压文件C:\Users\SW\Desktop\opencv-3.4.3-android-sdk\OpenCV-android-sdk\apk\OpenCV_3.4.3_Manager_3.43_arm64-v8a.apk

在cmd.exe中输入命令:adb install C:\Users\SW\Desktop\opencv-3.4.3-android-sdk\OpenCV-android-sdk\apk\OpenCV_3.4.3_Manager_3.43_arm64-v8a.apk

点击回车

手机安装此apk成功。

利用记事本打开C:\Users\SW\Desktop\opencv-3.4.3-android-sdk\OpenCV-android-sdk\apk下的readme.txt查看里面详细内容,安装哪一个apk需根据手机的cpu架构来选择安装。

9.Android项目清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.suoer.comeonhealth.firstoneopencvapp">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.FirstOneOpencvApp">
        <activity android:name=".HomeActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".MainActivity">

        </activity>
    </application>

</manifest>

10.运行Android项目至手机

点击MEAN BLUR按钮进入MainActivity界面,点击右上角菜单按钮加载图片,选择图片,界面显示原使图像和均值模糊后的图像。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/121632.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为防火墙ipsec vpn nat穿越2种场景配置案例

第一种方法&#xff0c;出口有nat设备&#xff08;这种方法最后电脑能上网&#xff0c;但不能和对端vpn通&#xff0c;配置检测没发现有问题&#xff0c;待以后再解决&#xff09;&#xff1a; 要实现分部电脑既能访问互联网又能和总部vpn连接 FW_A主要配置&#xff1a; acl …

为什么有的孩子玩着玩着就成了学霸?

毫不夸张地说&#xff0c;几乎所有的父母都想养出聪明宝宝&#xff0c;孩子上学之后能成为学霸就更省心了。 可“聪明”毕竟不能量化&#xff0c;不是说让孩子上几天课就能提升的。很多家长都在促进孩子大脑发育上使足了劲&#xff0c;可到头来却发现是在做“无用功”。 事实…

微服务-网关设计

文章目录 引言I 网关部署java启动jar包II 其他服务部署细节2.1 服务端api 版本号III 网关常规设置3.1 外部请求系统服务都需要通过网关访问3.2 第三方平台回调校验文件的配置IV 微服务日志跟踪4.1 打印线程ID4.2 封装线程池任务执行器4.3 将自身MDC中的数据复制给子线程4.4 微服…

设计模式之观察者(Observer)

事件处理模型 小朋友睡醒了就哭&#xff0c;饿 写程序模拟这个过程&#xff1a; v1:最简单的就是写程序一直观察着&#xff0c;什么时候哭了就进行处理 /*** 披着面向对象外衣的面向过程*/ public class Main1 {public static void main(String[] args) {boolean cry false…

Mabitys总结

一、ORM ORM(Object/Relation Mapping)&#xff0c;中文名称&#xff1a;对象/关系 映射。是一种解决数据库发展和面向对象编程语言发展不匹配问题而出现的技术。 使用JDBC技术时&#xff0c;手动实现ORM映射&#xff1a; 使用ORM时&#xff0c;自动关系映射&#xff1a; &am…

动态表单获取某一项值

<template><div><el-form :model"form" :rules"rules" ref"form"><el-row v-for"(item,index) in form.list" :key"index"><el-col :span"6"><el-form-item label"用户名称…

URI参数在Netty WebSocket中的处理方式,你了解吗?

URI参数传递 概述起因方法1方法2pom 主页传送门&#xff1a;&#x1f4c0; 传送 概述 WebSocket 是 HTML5 中实现实时通信的一种技术&#xff0c;它建立在 HTTP 协议上&#xff0c;但与传统的 HTTP 请求不同&#xff0c;WebSocket 连接一旦建立&#xff0c;就可以在客户端和服…

选择 REST ,还是 GraphQL

在本文中&#xff0c;简单比较 REST 和 GraphQL 的优点和缺点&#xff0c;以便您可以决定哪种 API 架构最适合您的项目 当我们要创建数据驱动的 Web 或移动应用程序&#xff0c;需要开发后台 API&#xff0c;通过它可以从后端服务器来访问或操作数据。目前最流行的 API 架构是…

Flutter的专属Skia引擎解析+用法原理

Skia是一款跨平台的2D图形库&#xff0c;是Google公司开发的&#xff0c;可以用于开发各种应用程序&#xff0c;如浏览器、游戏、移动应用程序等。Skia引擎的主要特点是速度快、可移植性强、占用的内存少、稳定性佳&#xff0c;适用于多种硬件平台。 Skia的目标是提供快速、高…

在Spring Boot中使用MyBatis访问数据库

MyBatis&#xff0c;这个对各位使用Java开发的开发者来说还是蛮重要的&#xff0c;我相信诸位在企业开发项目的时候&#xff0c;大多数采用的是Mybatis。使用MyBatis帮助我们解决各种问题&#xff0c;实际上这篇文章&#xff0c;基本上默认为可以跳过的一篇&#xff0c;但是为了…

什么是代理IP池?如何判断IP池优劣?

代理池充当多个代理服务器的存储库&#xff0c;提供在线安全和匿名层。代理池允许用户抓取数据、访问受限制的内容以及执行其他在线任务&#xff0c;而无需担心被检测或阻止的风险。代理池为各种在线活动&#xff08;例如网页抓取、安全浏览等&#xff09;提高后勤保障。 读完…

使用Python的requests库采集充电桩LBS位置经纬度信息

目录 一、引言 二、采集数据的流程 1、获取充电桩的URL地址 2、发送HTTP请求获取数据 3、解析数据获取经纬度信息 4、存储数据 三、代码实现 四、注意事项和优化建议 五、充电桩数据的后续利用 六、总结 一、引言 随着电动汽车的普及&#xff0c;充电设施的建设也日…

【JavaEESpring】Spring Web MVC⼊⻔

Spring Web MVC 1. 什么是 Spring Web MVC1.1 什么是 MVC ?1.2 是什么 Spring MVC? 2. 学习 Spring MVC2.1 建立连接2.2 请求2.3 响应 3. 相关代码链接 1. 什么是 Spring Web MVC 官⽅对于 Spring MVC 的描述是这样的&#xff1a; 1.1 什么是 MVC ? MVC 是 Model View C…

OpenCV实现手势虚拟拖拽

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 今天来学习一下如何使用OpenCV实现手势虚拟拖拽&#xff0c;欢迎大家一起前来探讨学习~ 一、主要步骤及库的功能介绍 1.主要步骤 要实现本次实验&#xff0c;主要步骤如下&#xff1a; 导入OpenCV库。通过OpenCV读取摄…

中文编程软件视频推荐,自学编程电脑推荐,中文编程开发语言工具下载

中文编程软件视频推荐&#xff0c;自学编程电脑推荐&#xff0c;中文编程开发语言工具下载 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#xff0c;而且可以开发大型的软件…

使用create-react-app脚手架创建react项目

查看npx版本&#xff1a; npx -v使用如下命令创建项目时&#xff1a; npx create-react-app demo报错&#xff1a; 解决&#xff1a; 以管理员身份运行cmd 然后再次创建项目&#xff0c;又报错&#xff1a; 经查得知&#xff1a;发生此错误是因为用户名中有空格&#xff0c;…

商城免费搭建之java商城 开源java电子商务Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

IPv6详解

目录: 第一部分 IPv6的诞生背景和引起的主要变化 第二部分 IPv6数据报的基本首部和扩展首部 第三部分 IPv6地址 第四部分 IPv4向IPv6过渡 第一部分 IPv6的诞生背景和引起的主要变化 一.IPv6的诞生背景 IPv4存在设计缺陷: IPv4的设计者最初并没有想到该协议会在全球范围内广…

NFS文件系统共享服务器实战

架设一台NFS服务器&#xff0c;并按照以下要求配置 准备 两台Linux虚拟机一台作为服务端server&#xff0c;一台作为客户端client server IPV4&#xff1a;192.168.110.136/24 client IPV4&#xff1a;192.168.110.134/24 两台服务器都需要关闭防火墙和seLinux 服…

element-ui中el-table数据合并行和列,应该怎么解决

最近接到一个任务,要实现一个数据报表,涉及到很多合并问题,一开始想着原生会简单点,实际上很麻烦,最后还是用elemen-ui中table自带的合并方法. 最终的效果是要做成这种:1.数据处理,后端返回来的数据是,一个大对象,包含三个数组,既然合并,肯定是要处理成一个数组,并且要把相同的…