深入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成功。

利用记事本打开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.rhkb.cn/news/185434.html

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

相关文章

统信UOS_麒麟KYLINOS创建网页桌面快捷方式

原文链接&#xff1a;统信UOS/麒麟KYLINOS创建网页桌面快捷方式 hello&#xff0c;大家好啊&#xff0c;今天给大家带来一篇使用命令行在统信UOS/麒麟KYLINOS创建网页桌面快捷方式的文章&#xff0c;主要用于构建云桌面模板及镜像模板的时候使用&#xff0c;欢迎大家浏览分享转…

数据库数据恢复—无备份,未开启binlog的MySQL误删除怎么恢复数据

数据库数据恢复环境&#xff1a; 一台本地windows sever操作系统服务器&#xff0c;服务器上部署mysql数据库单实例&#xff0c;引擎类型为innodb&#xff0c;表内数据存储所使用表空间类型为独立表空间。无数据库备份&#xff0c;未开启binlog。 数据库故障&分析&#xf…

05预测识别-依托YOLO V8进行训练模型的识别——对视频中的目标进行跟踪统计

上文中详细介绍了如何对视频进行抽帧,并对帧的图像进行目标识别。但在日常工作中,我们也会遇到需要对目标进行跟踪统计的情况,比如我们需要连续统计某一类目标有多少个的时候,如果单纯从帧中抽取图像的话,系统将无法判断是否为同一目标,从而造成目标数量统计的重复,导致…

SpringBoot整合Swagger3,赶紧整起来!

文章目录 一、Swagger是什么&#xff1f;二、使用步骤1.引入swagger3依赖2.添加swagger.conf配置类3.添加application.yml配置4.查看是否整合成功5.常用注解6.swagger美化 总结 一、Swagger是什么&#xff1f; Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用…

12 tcp协议详解

1、tcp的本性 tcp是一个悲观者&#xff0c;生下来就不信任网络&#xff0c;任务会发生丢包等&#xff0c;所以要从算法层面来保证可靠性。 2、TCP 包头格式 tcp的包头格式比UDP要复杂的多。 1.源端口号和目标端口号是不可少的&#xff0c;这一点和 UDP 是一样的。如果没有…

图形界面应用案例——关灯游戏(以及扩展)(python)

7.8 图形界面应用案例——关灯游戏 题目: [案例]游戏初步——关灯游戏。 关灯游戏是很有意思的益智游戏,玩家通过单击关掉(或打开)一盏灯。如果关(掉(或打开)一个电灯,其周围(上下左右)的电灯也会触及开关,成功地关掉所有电灯即可过关。 图7-43 关灯游戏运行效…

安防监控系统视频融合平台EasyCVR页面地图功能细节详解

安防监控视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力&#xff…

62、使用python进行rk3588开发板进行推流亚马逊云服务上,进行实时播放

基本思想:之前写了一套c++的推理和视频编解码,使用rk3588的mpp硬件进行编码和解码,然后使用RTSPServer进行推流,总是有问题,虽然可以使用ffplay和vlc进行拉取和播放,但是就是无法使用gstreamer推流到亚马逊云服务上,因为项目需求的紧急,所以先用python把流程跑同,后续…

linux基础指令【上篇】

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 引用 01. ls 指令2. pwd命…

FPGA的元素组件

注意&#xff1a;关于FPGA的元素这一块儿内容&#xff0c;稍有出入。例如&#xff1a;吉姆莱丁 著&#xff0c;陈会翔 译&#xff0c;由清华大学出版社出版的《构建高性能嵌入式系统》中提到&#xff1a;FPGA通常由查找表、触发器、块RAM、DSP切片、及其他功能元件等元素组成。…

互联网金融风控常见知识点

1.怎么做互联网金融风控 首先风险不是都是坏的&#xff0c;风险是有价值的。也就是风险的VaR值(Value at Risk) 对于互联网信贷风控&#xff0c;是要把风险和收益做到更合理的平衡&#xff0c;在控制风险水平的情况下使得收益更高。 所以&#xff0c;做风控的不是一味地追求耕…

设计模式—结构型模式之桥接模式

设计模式—结构型模式之桥接模式 将抽象与实现解耦&#xff0c;使两者都可以独立变化。 在现实生活中&#xff0c;某些类具有两个或多个维度的变化&#xff0c;如图形既可按形状分&#xff0c;又可按颜色分。如何设计类似于 Photoshop 这样的软件&#xff0c;能画不同形状和不…

flink的带状态的RichFlatMapFunction函数使用

背景 使用RichFlatMapFunction可以带状态来决定如何对数据流进行转换&#xff0c;而且这种用法非常常见&#xff0c;根据之前遇到过的某个key的状态来决定再次遇到同样的key时要如何进行数据转换&#xff0c;本文就来简单举个例子说明下RichFlatMapFunction的使用方法 RichFl…

OceanBase 如何通过日志观测冻结转储流程?

本文旨在通过日志解析 OceanBase 的冻结转储流程&#xff0c;以其冻结检查线程为切入点&#xff0c;以租户&#xff08;1002&#xff09;的线程名为例。 作者&#xff1a;陈慧明&#xff0c;爱可生测试工程师&#xff0c;主要参与 DMP 和 DBLE 自动化测试项目。 爱可生开源社区…

技术分享|基于 Cluster API 的 Kubernetes 集群生命周期管理

作者&#xff1a;SmartX SKS 产品研发工程师 杨海剑 背景 容器的发展催生了容器编排技术&#xff0c;而容器编排技术反过来又推动了容器的发展。容器编排领域则一度出现了 Swarm、Mesos 和 Kubernetes 等百家争鸣的局面。但随着 Kubernetes 脱颖而出&#xff0c;Kubernetes 成为…

早安心语微语早读,好好善待自己,珍惜今天,期待明天

1、保持阳光心态&#xff0c;积极面对人生&#xff0c;每个人&#xff0c;都沿着不同的轨道在活着&#xff0c;人生是一趟单程车&#xff0c;我们最应该做的&#xff0c;就是好好善待自己&#xff0c;珍惜今天&#xff0c;期待明天&#xff0c;那些走过的&#xff0c;错过的&am…

零代码编程:用ChatGPT批量将Mp4视频转为Mp3音频

文件夹中有很多mp4视频文件&#xff0c;如何利用ChatGPT来全部转换为mp3音频呢&#xff1f; 在ChatGPT中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个批量将Mp4视频转为Mp3音频的任务&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;…

2023最新版JavaSE教程——第4天:流程控制语句之循环语句

目录 一、循环语句二、for循环2.1 基本语法2.2 应用举例2.3 练习 三、while循环3.1 基本语法3.2 应用举例3.3 练习 四、do-while循环4.1 基本语法4.2 应用举例4.3 练习4.4 对比三种循环结构4.5 "无限"循环4.5.1 基本语法4.5.2 应用举例 4.6 嵌套循环(或多重循环)4.6.…

网络流量分类概述

1. 什么是网络流量&#xff1f; 一条网络流量是指在一段特定的时间间隔之内&#xff0c;通过网络中某一个观测点的所有具有相同五元组(源IP地址、目的IP地址、传输层协议、源端口和目的端口)的分组的集合。 比如(10.134.113.77&#xff0c;47.98.43.47&#xff0c;TLSv1.2&…

【K8s集群离线安装-kubeadm】

1、kubeadm概述 kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。这个工具能通过两条指令快速完成一个kubernetes集群的部署。 2、环境准备 2.1 软件环境 软件版本操作系统CentOS 7Docker19.03.13K8s1.23 2.2 服务器 最小硬件配置&#xff1a;2核CPU、2G内存…