android openCV检测图像的基本特征,包括Canny边缘检测、Harris角点检测、霍夫直线检测-基于Android studio
实现平台:windows下的Android studio1.4
依赖库:openCV3.1.0
程序安装平台:Android6.0
实现的功能:从手机中选择一张图片,检测图片的基本特征,通过menu菜单选择要检测的特征,包括Canny边缘检测、Harris角点检测、霍夫直线检测
说明:对于检测图像的基本特征的算法就不加以详细说明了,网上的资料很多,现在这里主要介绍算法以及代码的编写
1.在Androidmanifest.xml文件中添加如下代码:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.wangshuailpp.myapplication" > <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
这里最重要的是,表示要开启手机内存的读取权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
2.在布局文件中activity_main.xml文件中添加一个图片控件:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <ImageView android:id="@+id/Picture" android:layout_height="fill_parent" android:layout_width="fill_parent" android:visibility="visible" /> </RelativeLayout>
3.菜单menu_main.xml文件中添加成员:
<menu 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" tools:context=".MainActivity"> <item android:id="@+id/Canny" android:title="Canny" android:showAsAction="never" /> <item android:id="@+id/Harris" android:title="Harris" android:showAsAction="never" /> <item android:id="@+id/Hough" android:title="Hough" android:showAsAction="never" /> </menu>
4.在MainActivity.java主类中的代码:
package com.example.wangshuailpp.myapplication; /* 功能介绍:深入OpenCV Android应用开发第二章代码,检测图像的基本特征 包括了Canny边缘检测法Sobel边缘检测法等 实现步骤:1.从手机中取出一张图片作为原始图片,通过点击menu对应的按钮开始选择图片 2.通过menu按钮选择要对照片进行的图像处理 */ import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.ImageView; import android.widget.Toast; import org.opencv.android.BaseLoaderCallback; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; import org.opencv.android.Utils; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.Point; import org.opencv.core.Scalar; import org.opencv.imgproc.Imgproc; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.Random; public class MainActivity extends ActionBarActivity {private final static int CANNY = 0; private final static int HARRIS = 1; private final static int HOUGH = 2; private final static String TAG = "infor"; private Mat src = null;//定义一个Mat型类用于临时存放选择的图片 private Mat image = null;//用于存放得到的图片 private Mat des = null;//用于临时存放Mat型类的图片 private Bitmap resultBitmap; private ImageView pictureView = null;//定义一个ImageView类视图用于存放选择的图片 private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {@Override public void onManagerConnected(int status) {switch (status){case LoaderCallbackInterface.SUCCESS:/*在这里执行自己的语句*/ break; default:super.onManagerConnected(status); break; }}}; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pictureView = (ImageView)findViewById(R.id.Picture); }/*启动openCV*/ @Override protected void onResume() {super.onResume(); OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_1_0, this, mOpenCVCallBack); }@Override public boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; }/*在这里选取要进行的操作*/ @Override public boolean onOptionsItemSelected(MenuItem item) {// Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //对应Canny边缘检测的按钮 if (id == R.id.Canny) {/*下面对通过Intent对象得到选择图片的Activity,最后返回图片的信息,得到图片*/ Intent pictureSelectIntent = new Intent(Intent.ACTION_PICK);//设置Action pictureSelectIntent.setType("image/");//设置数据的类型 startActivityForResult(pictureSelectIntent,CANNY); return true; }//对应Harris边缘检测的按钮 if (R.id.Harris == id){Intent pictureSelectIntent = new Intent(Intent.ACTION_PICK); pictureSelectIntent.setType("image/"); startActivityForResult(pictureSelectIntent,HARRIS); return true; }//对应Hough的直线检测按钮 if(R.id.Hough == id){Intent pictureSelectIntent = new Intent(Intent.ACTION_PICK); pictureSelectIntent.setType("image/"); startActivityForResult(pictureSelectIntent,HOUGH); return true; }return super.onOptionsItemSelected(item); }/*调用StartActivityForResult后的回调函数 * 在这个函数里面得到图片然后进行相应的处理 * */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data); if(RESULT_OK == resultCode){switch(requestCode){case CANNY:try {Log.i(TAG,"onActivityResult00000000000"); image = GetPicture(data); Toast.makeText(MainActivity.this, "图片选取成功", Toast.LENGTH_SHORT).show(); Log.i(TAG,"onActivityResult11111111111"); resultBitmap = MyCanny(image); Log.i(TAG,"onActivityResult22222222222222"); pictureView.setImageBitmap(resultBitmap); } catch (FileNotFoundException e) {e.printStackTrace(); }break; case HARRIS:try {image = GetPicture(data);//得到图片 Toast.makeText(MainActivity.this, "图片选取成功", Toast.LENGTH_SHORT).show(); Log.i(TAG,"onActivityResult11111111111"); resultBitmap = MyHarris(image);//角点检测的图像处理 Log.i(TAG,"onActivityResult22222222222222"); pictureView.setImageBitmap(resultBitmap); } catch (FileNotFoundException e) {e.printStackTrace(); }case HOUGH:try {image = GetPicture(data);//得到图片 Toast.makeText(MainActivity.this, "图片选取成功", Toast.LENGTH_SHORT).show(); Log.i(TAG,"onActivityResult11111111111"); resultBitmap = MyHoughLine(image); pictureView.setImageBitmap(resultBitmap); }catch (FileNotFoundException e) {e.printStackTrace(); }}}}/*得到图片*/ public Mat GetPicture(Intent data) throws FileNotFoundException {/*下面的代码是获得手机内的图片*/ final Uri imageUri = data.getData();//得到图片的路径 final InputStream imageStream = getContentResolver().openInputStream(imageUri);//得到基于路径的流文件 final Bitmap selectImage = BitmapFactory.decodeStream(imageStream);//得到了图片的位图 /*下面将位图转换成Mat型,可以进行图片的处理*/ src = new Mat(selectImage.getHeight(),selectImage.getWidth(), CvType.CV_8UC4); Utils.bitmapToMat(selectImage,src); return src; }/*下面进行图片的处理 * * */ /*Canny边缘处理*/ public Bitmap MyCanny(Mat src){Bitmap result; Mat grayMat = new Mat(); Mat cannyEdges = new Mat(); Log.i(TAG,"MyCanny0000000000"); /*将图片转换成灰度图*/ Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGR2GRAY); Log.i(TAG, "MyCanny1111111111111111"); /*得到边缘图,这里最后两个参数控制着选择边缘的阀值上限和下限*/ Imgproc.Canny(grayMat,cannyEdges,50,300); Log.i(TAG, "MyCanny222222222222222222222222"); /*将Mat图转换成位图*/ result = Bitmap.createBitmap(src.cols(),src.rows(),Bitmap.Config.ARGB_8888); Utils.matToBitmap(cannyEdges,result); Log.i(TAG, "MyCanny3333333333333333333333"); return result; }/*Harris角点检测*/ public Bitmap MyHarris(Mat src){Bitmap resultHarris; Mat grayMat = new Mat(); Mat corners = new Mat(); Log.i(TAG,"MyHarris00000000000000000000"); /*将图片转换成灰度图*/ Imgproc.cvtColor(src,grayMat,Imgproc.COLOR_BGR2GRAY); Log.i(TAG, "MyHarris1111111111111111111"); /*找出角点*/ Mat tempDst = new Mat(); Imgproc.cornerHarris(grayMat,tempDst,2,3,0.04); Log.i(TAG, "MyHarris2222222222222222222"); /*归一化Harris角点的输出*/ Mat tempDstNorm = new Mat(); Core.normalize(tempDst,tempDstNorm,0,255,Core.NORM_MINMAX); Core.convertScaleAbs(tempDstNorm, corners); Log.i(TAG, "MyHarris33333333333333333333"); /*在新的图片上绘制角点*/ Random r = new Random(); for(int i = 0; i < tempDstNorm.cols(); i++){for (int j = 0;j <tempDstNorm.rows(); j++){double[] value = tempDstNorm.get(j,i); if(value[0] > 250){//决定了画出哪些角点,值越大选择画出的点就越少。如果程序跑的比较慢,就是由于值选取的太小,导致画的点过多 Imgproc.circle(corners, new Point(i,j),5,new Scalar(r.nextInt(255)),2); }}}Log.i(TAG,"MyHarris4444444444444444444444444"); /*将Mat图转换成位图*/ resultHarris = Bitmap.createBitmap(src.cols(),src.rows(),Bitmap.Config.ARGB_8888);//这一步至关重要,必须初始化Bitmap对象的大小 Utils.matToBitmap(corners, resultHarris); return resultHarris; }/*Hough直线检测*/ public Bitmap MyHoughLine(Mat src){Bitmap resultHough; Mat grayMat = new Mat(); Mat cannyEdges = new Mat(); Mat lines = new Mat(); Mat origination = new Mat(src.size(),CvType.CV_8UC1); src.copyTo(origination);//拷贝 /*通过Canny得到边缘图*/ Imgproc.cvtColor(origination,grayMat,Imgproc.COLOR_BGR2GRAY); Imgproc.Canny(grayMat,cannyEdges,50,300); //Mat cannyEdges = new Mat(resultHough.getHeight(),resultHough.getWidth(),CvType.CV_8UC1); Log.i(TAG,"MyHoughLine00000000000000"); /*获得直线图*/ Imgproc.HoughLinesP(cannyEdges,lines,1,Math.PI/180,10,0,50); Log.i(TAG, "MyHoughLine111111111111111"); Mat houghLines = new Mat(); houghLines.create(cannyEdges.rows(),cannyEdges.cols(),CvType.CV_8UC1); Log.i(TAG, "MyHoughLine2222222222222222222"); /*在图线的上绘制直线*/ for(int i = 0;i < lines.rows();i++){double[] points = lines.get(i,0); if(null != points){double x1,y1,x2,y2; x1 = points[0]; y1 = points[1]; x2 = points[2]; y2 = points[3]; Point pt1 = new Point(x1,y1); Point pt2 = new Point(x2,y2); /*在一幅图像上绘制直线*/ Imgproc.line(houghLines,pt1,pt2,new Scalar(55,100,195),3); }}Log.i(TAG, "MyHoughLine3333333333333333333333333"); resultHough = Bitmap.createBitmap(src.cols(),src.rows(),Bitmap.Config.ARGB_8888); Utils.matToBitmap(houghLines,resultHough); Log.i(TAG, "MyHoughLine44444444444444444444444444444"); return resultHough; } }
这里需要注意的事项:
1.在霍夫直线检测中有一句代码,很多网上的程序都不对,都写成了
double[] points = lines.get(0,i);
其实是
double[] points = lines.get(i,0);
写成第一种,会导致只会画出一条直线。
其他的都可以在程序的解释中看到,在这里就不都说了,下面直接贴结果,分别是原图,Canny,Harri,霍夫直线。
android openCV检测图像的基本特征,包括Canny边缘检测、Harris角点检测、霍夫直线检测-基于Android studio相关推荐
- Android OpenCV(三十二):霍夫直线检测
霍夫变换利用点与线之间的对偶性,将图像空间中直线上离散的像素点通过参数方程映射为霍夫空间中的曲线,并将霍夫空间中多条曲线的交点作为直线方程的参数映射为图像空间中的直线.给定直线的参数方程,可以利用霍夫 ...
- OpenCV标准霍夫直线检测详解
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转载自:OpenCV学堂 霍夫直线检测 对于图像来说可以从笛卡 ...
- QT+opencv学习笔记(5)——霍夫直线检测、圆检测及椭圆检测
开发环境为:win10+QT5.8+opencv3.2 Hough变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛.最基本的Hough变换是从黑白图像中检测直线,还可以经过改进检测圆.椭 ...
- c++版本opencv(36.霍夫直线检测37.直线类型与线段-)
c++版本opencv(36.霍夫直线检测37.直线类型与线段-) 一.36.霍夫直线检测- 二,37.直线类型与线段- 来自网易云课堂贾志刚老师 一.36.霍夫直线检测- 同一条直线上的点,r和c塔 ...
- 基于opencv的c++图像处理(霍夫直线检测与最小二乘法直线拟合)
前言 基于opencv的c++接口,实现标准的霍夫直线检测.基于统计概率的霍夫直线检测.以及最小二乘法直线拟合. 相关的opencv接口解析 CV_EXPORTS_W void HoughLines( ...
- OpenCV霍夫直线检测的实例(附完整代码)
OpenCV霍夫直线检测的实例 OpenCV霍夫直线检测的实例 OpenCV霍夫直线检测的实例 #include <opencv2/imgproc.hpp> #include <op ...
- 通过霍夫直线检测方式获取直线,自定义提取直线(提取出两条接近平行的直线),将直线进行拟合
由于项目的需要,需要使用霍夫直线检测进行处理图像.这里进行笔记记录,话不多说,先上代码: #include <opencv2/opencv.hpp> #include <opencv ...
- opencv值霍夫直线检测原理
转载于CheerM的博客园博客 霍夫变换--直线检测 考古debug,其实很久之前就解决的bug--一直忘记过来改文章-.欸 =============================原文====== ...
- 【OpenCv】霍夫直线检测
文章目录 前言 1 原理 2 算法流程 3 优缺点 前言 Hough变换是实现边缘检测的一种有效方法,其基本思想是将测量空间的一点变换到参量空间的一条曲线或曲面,而具有同一参量特征的点变换后在参量 ...
最新文章
- 2W 字详解 Redis 6.0 集群环境搭建实践
- Eclipse旧版本Luna SR2(版本4.4.2)下载地址
- 计算机视觉与深度学习 | 基于DNN神经网络实现人的年龄及性别预测(代码类)
- 3dContactPointAnnotationTool开发日志(三三)
- android 不同型号的终端的UI适配--一种解决方法
- C# 进程Process基本的操作说明
- Vivado HLS基本应用
- ethtool源码分析
- SAP License:一句话让你明白FICO
- CentOS linux修改主机名
- Macbook下ffmpeg下载失败问题解决
- MySQL的自定义函数
- conda 小tips
- iphone13 Pro的运行内存是6gb
- div+css+jquery仿写HTML京东首页的练习及一些关于oo css的总结
- 1. 《计算机网络》概述,物理层,数据链路层
- 7-13 旭旭的交友标准PTA
- Simpsons’ Hidden Talents辛普森一家的隐藏天赋(next数组和kmp字符串匹配)
- 百知教育浅谈亚马逊跨境电商
- catia v5法矢数据软件_CATIA V5完全学习手册