前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android调用OpenCV2.4.10实现二维码区域定位

Android调用OpenCV2.4.10实现二维码区域定位

作者头像
砸漏
发布2020-11-03 21:21:11
6860
发布2020-11-03 21:21:11
举报
文章被收录于专栏:恩蓝脚本恩蓝脚本

Android上使调用OpenCV 2.4.10 实现二维码区域定位(Z-xing 码),该文章主要用于笔者自己学习中的总结,暂贴出代码部分,待以后有时间再补充算法的详细细节。

Activity class Java 文件

代码语言:javascript
复制
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 文件

代码语言:javascript
复制
<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 文件

代码语言:javascript
复制
<resources  
<string name="app_name" Code</string  
<string name="desc" Take picture button</string  
</resources  

style.xml 文件(理论上是可以自动生成,若自动生成内容有错,可以参考)

代码语言:javascript
复制
<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 文件

代码语言:javascript
复制
<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  

以上就是本文的全部内容,希望对大家的学习有所帮助。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档