Android调用OpenCV2.4.10实现二维码区域定位
作者:BusyMonkey 发布时间:2023-06-05 10:17:32
标签:Android,OpenCV2.4.10,二维码
Android上使调用OpenCV 2.4.10 实现二维码区域定位(Z-xing 码),该文章主要用于笔者自己学习中的总结,暂贴出代码部分,待以后有时间再补充算法的详细细节。
Activity class Java 文件
package cn.hjq.android_capture;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.*;
import org.opencv.highgui.*;
import org.opencv.imgproc.*;
import org.opencv.utils.Converters;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
public class capture extends Activity {
private SurfaceView picSV;
private Camera camera;
private String strPicPath;
//OpenCV类库加载并初始化成功后的回调函数,在此我们不进行任何操作
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:{
} break;
default:{
super.onManagerConnected(status);
} break;
}
}
};
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setContentView(R.layout.main);
picSV = (SurfaceView) findViewById(R.id.picSV);
picSV.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
picSV.getHolder().addCallback(new MyCallback());
}
private class MyCallback implements Callback{
//我们在SurfaceView创建的时候就要进行打开摄像头、设置预览取景所在的SurfaceView、设置拍照的参数、开启预览取景等操作
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();//打开摄像头
camera.setPreviewDisplay(picSV.getHolder());//设置picSV来进行预览取景
Parameters params = camera.getParameters();//获取照相机的参数
params.setPictureSize(800, 480);//设置照片的大小为800*480
params.setPreviewSize(800, 480);//设置预览取景的大小为800*480
params.setFlashMode("auto");//开启闪光灯
params.setJpegQuality(50);//设置图片质量为50
camera.setParameters(params);//设置以上参数为照相机的参数
camera.startPreview();
}
catch (IOException e) { //开始预览取景,然后我们就可以拍照了
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//当SurfaceView销毁时,我们进行停止预览、释放摄像机、垃圾回收等工作
camera.stopPreview();
camera.release();
camera = null;
}
}
public void takepic(View v){
//在我们开始拍照前,实现自动对焦
camera.autoFocus(new MyAutoFocusCallback());
}
private class MyAutoFocusCallback implements AutoFocusCallback{
@Override
public void onAutoFocus(boolean success, Camera camera) {
//开始拍照
camera.takePicture(null, null, null, new MyPictureCallback());
}
}
private class MyPictureCallback implements PictureCallback{
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Matrix matrix = new Matrix();
matrix.preRotate(90);
bitmap = Bitmap.createBitmap(bitmap ,0,0, bitmap.getWidth(),
bitmap.getHeight(),matrix,true);
strPicPath =
Environment.getExternalStorageDirectory()+"/1Zxing/"+System.currentTimeMillis()+".jpg";
FileOutputStream fos = new FileOutputStream( strPicPath );
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
Handler mHandler = new Handler();
mHandler.post(mRunnable);
camera.startPreview();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
public boolean onTouchEvent (MotionEvent event)
{
int Action = event.getAction();
if ( 1 == Action ) {
camera.autoFocus(new MyAutoFocusCallback1());
}
return true;
}
private class MyAutoFocusCallback1 implements AutoFocusCallback {
@Override
public void onAutoFocus(boolean success, Camera camera) {
}
}
@Override
public void onResume(){
super.onResume();
//通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是
//OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存在于OpenCV安装包的apk目录中
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_10, this, mLoaderCallback);
}
Runnable mRunnable = new Runnable() {
public void run() {
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
String strMissingTime = null;
Mat srcColor = new Mat(), srcColorResize = new Mat();
Mat srcGray = new Mat(), srcGrayResize = new Mat(), srcGrayResizeThresh = new Mat();
srcGray = Highgui.imread(strPicPath, 0);
srcColor = Highgui.imread(strPicPath, 1);
Imgproc.resize(srcGray, srcGrayResize, new Size(srcGray.cols()*0.2,srcGray.rows()*0.2));
Imgproc.resize(srcColor, srcColorResize, new Size(srcGray.cols()*0.2,srcGray.rows()*0.2));
long start = System.currentTimeMillis();
//二值化加轮廓寻找
Imgproc.adaptiveThreshold(srcGrayResize, srcGrayResizeThresh, 255,
Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,
Imgproc.THRESH_BINARY, 35, 5);
Imgproc.findContours(srcGrayResizeThresh, contours, new Mat(),
Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_NONE);
long end = System.currentTimeMillis();
strMissingTime = String.valueOf( end - start );
strMissingTime = strMissingTime + "\r";
//轮廓绘制
for ( int i = contours.size()-1; i >= 0; i-- )
{
MatOfPoint2f NewMtx = new MatOfPoint2f( contours.get(i).toArray() );
RotatedRect rotRect = Imgproc.minAreaRect( NewMtx );
Point vertices[] = new Point[4];
rotRect.points(vertices);
List<Point> rectArea = new ArrayList<Point>();
for ( int n = 0; n < 4; n ++ )
{
Point temp = new Point();
temp.x = vertices[n].x;
temp.y = vertices[n].y;
rectArea.add(temp);
}
Mat rectMat = Converters.vector_Point_to_Mat(rectArea);
double minRectArea = Imgproc.contourArea( rectMat );
Point center = new Point();
float radius[] = {0};
Imgproc.minEnclosingCircle(NewMtx, center, radius);
if(
Imgproc.contourArea( contours.get(i)) < 300 ||
Imgproc.contourArea( contours.get(i)) > 3000
|| minRectArea < radius[0]*radius[0]*1.57
) contours.remove(i);
}
Imgproc.drawContours(srcColorResize, contours, -1, new Scalar(255,0,0));
Highgui.imwrite(Environment.getExternalStorageDirectory()+"/1Zxing/"
+System.currentTimeMillis()+"contour.jpg", srcColorResize);
File file=new File(Environment.getExternalStorageDirectory()+"/1Zxing/","log.txt");
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
out.write(strMissingTime);
out.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
};
}
layout.xml 文件
<FrameLayout 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"
tools:context=".MainActivity" >
<SurfaceView
android:id="@+id/picSV"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</SurfaceView>
<ImageButton
android:contentDescription="@string/desc"
android:onClick="takepic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|top"
android:src="@android:drawable/ic_menu_camera" />
</FrameLayout>
string.xml 文件
<resources>
<string name="app_name">Code</string>
<string name="desc">Take picture button</string>
</resources>
style.xml 文件(理论上是可以自动生成,若自动生成内容有错,可以参考)
<resources>
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
</style>
</resources>
AndroidManifest.xml 文件
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.hjq.android_capture"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission
android:name="android.permission.CAMERA"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".capture" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
来源:http://blog.csdn.net/Dopamy_BusyMonkey/article/details/42639169


猜你喜欢
- 本文实例为大家分享了Android Studio实现简易进制转换计算器的具体代码,供大家参考,具体内容如下1、问题描述设计并实现一个数制转换
- 发展历史Gradle 的依赖管理是一个从开始接触 Android 开发就一直伴随着我们的问题(作者是Andro
- 很多朋友问小编springboot项目中怎么集成Swagger呢?swagger世界上最好的api管理工具前言我们为什么要使用api管理工具
- hibernate一级缓存和二级缓存的区别缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用
- 本文介绍idea的安装和基本使用首先保证JDK正常安装及配置下载地址:https://www.jetbrains.com/idea/down
- 数组分页查询出全部数据,然后再list中截取需要的部分。mybatis接口List<Student> queryStudents
- 为了实现自定义的Menu和ContextMenu效果,下面演示代码通过派生ProfessionalColorTable类,在自定义的类中重写
- 迷宫项目实现设计文档项目介绍:一个网格迷宫由n行m列的单元格组成,每个大院个要么是空地(用0表示),要么是障碍物(用1表示)。你的任务是找一
- mybatis官网中文文档:https://mybatis.org/mybatis-3/zh/sqlmap-xml.htmlmybatis-
- C#WinForm程序设计之图片浏览器,这次我们一起做一个图片查看器,这个图片查看器的原始图如下:我们首先来介绍一下这个原始图的构成:左边上
- 目录1.启动分为两种方式2.如何测量一个应用的启动时间3.应用启动的流程4.减少应用的启动时间的耗时5.如何设计延迟加载DelayLoad1
- 本文实例讲述了C#中Winform窗体Form的关闭按钮变灰色的方法,对C#程序设计有一定的借鉴价值,分享给大家供大家参考之用。具体方法如下
- 整合Spring Data JPAJPA (Java Persistence API)和 Spring Data 是两个范畴的概念。Hibe
- 描述说明:public class TryCatchStu { /*try catch:自己处理异常 *t
- 本文实例讲述了Android启动画面的实现方法。分享给大家供大家参考。具体分析如下:在应用程序中经常用到启动画面,会启动一个后台线程为主程序
- 这篇文章主要介绍了SpringBoot如何通过devtools实现热部署,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考
- 单例模式动机有时候只有一个类的实例是很重要的。比如,一个系统应该只有一个窗口管理实例。单例模式是最简单设计模式:类负责实例化自己,确保只有一
- C#中的null与SQL中的NULL是不一样的,SQL中的NULL用C#表示出来就是DBNull.Value。注意:SQL参数是不能接受C#
- 对于导航组件的使用方式不是本文的重点,具体使用可以参考官方文档,导航组件框架是通过f
- Java Collection API提供了一些列的类和接口来帮助我们存储和管理对象集合。其实Java中的集合工作起来像是一个数组,不过集合