深入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"><Buttonapp: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;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_home);Button bMean=findViewById(R.id.bMean);bMean.setOnClickListener(new View.OnClickListener() {@Overridepublic 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"><ImageViewandroid:layout_weight="0.5"android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/ivImage"></ImageView><ImageViewandroid: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) {@Overridepublic void onManagerConnected(int status) {switch (status){case SUCCESS://在这里完成break;default:super.onManagerConnected(status);break;}}};@Overrideprotected 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);}}@Overrideprotected void onResume() {super.onResume();OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION,this,mOpenCVCallBack);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.menu_main,menu);return true;}@Overridepublic 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);}@Overrideprotected 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成功。OpenCV Manager安装成功以后,运行此项目。FirstOneOpencvApp如果被进程杀掉或此App完全退出,需重新运行OpenCV Manager项目,否则FirstOneOpencvApp项目无法使用OpenCV提供的函数实现功能。

利用记事本打开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"><applicationandroid: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界面,点击右上角菜单按钮加载图片,选择图片,界面显示原使图像和均值模糊后的图像。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Springboot】基于注解式开发Springboot-Vue3整合Mybatis-plus实现分页查询(二)——前端el-pagination实现

系列文章 【Springboot】基于注解式开发Springboot-Vue3整合Mybatis-plus实现分页查询—后端实现 文章目录 系列文章系统版本实现功能实现思路后端传入的数据格式前端el-table封装axois接口引入Element-plus的el-pagination分页组件Axois 获取后台数据 系统版本 后端&#xf…

内存映射:PS和PL DDR3的一些区别

之前写的一些资料&#xff1a; PS与PL互联与SCU以及PG082-CSDN博客 参考别人的资料&#xff1a; PL读写PS端DDR的设计_pl读写ps端ddr数据-CSDN博客 xilinx sdk、vitis查看地址_vitis如何查看microblazed地址_yang_wei_bk的博客-CSDN博客 可见&#xff0c;PS端的DDR3需要从…

【友提】2023年“思维100”编程比赛开始报名,名额有限报名抓紧

根据官方昨天发布的通知&#xff0c;2023年上海市“科学小公民”实践展示活动之“思维100”STEM应用能力编程活动&#xff08;秋季&#xff09;开始报名了&#xff0c;为便于大家了解&#xff0c;六分成长为大家整理关键信息如下。为便于叙述&#xff0c;该活动简称为思维100编…

[autojs]逍遥模拟器和vscode对接

第一步&#xff1a;启动autojs服务 第二步&#xff1a;去cmd查看ip地址&#xff0c;输入ipconfig 第三步&#xff1a;打开逍遥模拟器中的sutojs-左上角- 连接电脑&#xff0c;然后输入WLAN或者其他ip也行&#xff0c;根据自己电脑实际情况确认 此时vscode显示连接成功。我们写…

Linux文件缓冲区

文章目录 1. 缓冲区现象2. 用户级和系统级缓冲区3. 缓冲区刷新4. 为什么要有缓冲区5. 文件打印的全缓冲6. 模拟实现C语言文件标准库 本章gitee代码仓库&#xff1a;重定向、模拟C语言文件标准库 1. 缓冲区现象 我们这里分别调用了4个差不多的函数&#xff0c;但是结果是有一定差…

深度解析找不到msvcp120.dll相关问题以及解决方法

​在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp120.dll丢失”。这个错误通常会导致某些应用程序无法正常运行&#xff0c;给用户带来很大的困扰。那么&#xff0c;如何解决msvcp120.dll丢失的问题呢&#xff1f;本文将为大家介绍…

leetcode刷题日记:111. Minimum Depth of Binary Tree(二叉树的最小深度)

给我们一个二叉树&#xff0c;我们应该如何来求二叉树的最小深度呢&#xff1f; 二叉树的最小深度指的是叶子结点到所处的位置最小的&#xff0c;这就是二叉树的最小深度&#xff0c;也就是说我们要找的是离根结点最近的叶子结点。如果我们从根结点向下出发寻找叶子节点&#x…

overflow: auto滚动条跳到指定位置

点击对应模块跳转页面&#xff0c;滚动到对应模块&#xff0c;露出到可视范围 代码&#xff1a; scrollToCurrentCard() {// treeWrapper是包裹多个el-tree组件的父级元素&#xff0c;也是设置overflow:auto的元素let treeWrapper document.getElementsByClassName(treeWrapp…

STM32笔记—定时器

目录 一、TIM简介 二、基本定时器&#xff08;TIM6和TIM7&#xff09; 1. TIM6和TIM7简介 2. TIM6和TIM7的主要特性 3. TIM6和TIM7的功能 3.1 时基单元 3.2 计数模式 3.3 时钟源 三、通用定时器 1. TIMx(2、3、4、5)简介 2. TIMx主要功能 3. 时钟选择 4. 影子寄存…

【算法练习Day46】判断子序列不同的子序列

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 判断子序列不同的子序列总结…

450. 删除二叉搜索树中的节点

题目描述 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除节点可分为两个步骤&#x…

uniapp中picker 获取时间组件如何把年月日改成年月日默认时分秒为00:00:00

如图所示&#xff0c;uniapp中picker组件的日期格式为&#xff1a; 但后端要 2023-11-08 00:00:00格式 如何从2023-11-08转化为 2023-11-08 00:00:00&#xff1a;&#x1f447; const date new Date(e.detail.value);//"2023-11-17" date.setHours(0, 0, 0); // 2…

C语言从入门到精通之【数据类型和关键字】

数据类型在程序使用之前已经预先设定好了&#xff0c;在整个程序的运行过程中没有变化&#xff0c;这些称为常量&#xff08;constant&#xff09;。其他数据类型在程序运行期间可能会改变或被赋值&#xff0c;这些称为变量&#xff08;variable&#xff09;。 变量类型有几种…

复盘一个诡异的Bug

该Bug的诡异之处在于这是一个由多种因素综合碰撞之后形成的综合体。纵观整个排查过程&#xff0c;一度被错误的目标误导&#xff0c;花费大量功夫后才找到问题点所在&#xff0c;成熟的组件在没有确凿证据之前不能随意怀疑其稳定性。 前言 此前在接入两台粒径谱仪&#xff08;…

Android sqlite 使用简介

进行Android应用开发时经常会用到数据库。Android系统支持sqlite数据库&#xff0c;在app开发过程中很容易通过SQLiteOpenHelper使用数据库&#xff0c;SQLiteOpenHelper依赖于Context对象&#xff0c;但是基于uiatomator1.0和Java程序等无法获取Context的应用如何使用数据库呢…

html与django实现多级数据联动

html与django实现多级数据联动 1、流程 1、进入页面后先获取年级数据 2、选择年级后获取院级数据 3、选择院级后获取层次数据 4、选择层次数据后获取专业数据 2、html代码 <p style"margin-top: 10px;"><label>年级</label><select id"…

什么是微服务自动化测试?

什么是微服务&#xff1f; 微服务 - 也称为微服务架构 - 是一种构建方式&#xff0c;它将应用程序构建为松散耦合服务的集合&#xff0c;具有完整的业务功能。微服务架构允许连续交付/部署大型复杂应用程序。本文将概述自动微服务测试工具和最佳实践。 它还使组织能够发展其技…

Ubuntu诞生已经19年了

导读2004 年 10 月 20 日&#xff0c;Ubuntu 4.10 正式发布&#xff0c;代号‘Warty Warthog’。 2004 年 10 月 20 日&#xff0c;Ubuntu 4.10 正式发布&#xff0c;代号‘Warty Warthog’。 ▲ Ubuntu 4.10 与最新版 Ubuntu 23.10 的对比 作为 Ubuntu 第一个版本&#xff0…

Postman基本页面和请求/响应页签介绍

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 一、Postman的界面介绍 Home主页、Workspace工作空间、Collections集合、Environments环境变量、Mock Server虚拟服务器、Mo…

Direct3D粒子系统

粒子和点精灵 粒子(是种微小的物体,在数学上通常用点来表示其模型。所以显示粒子时,使用点图元(由 D3 DPRIMITIVETYPE类型的D3 DPT POINTLIST枚举常量表示)是一个很好的选择。但是光栅化时,点图元将被映射为一个单个像素。这样就无法为我们提供很大的灵活性,因为实际应用…