首页 > 系统 > Android > 正文

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

2019-10-22 18:14:33
字体:
来源:转载
供稿:网友

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> 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表