Android calls OpenCV2.4. 10 to locate the two dimensional code area

  • 2021-08-21 21:36:18
  • OfStack

On Android, call OpenCV 2.4. 10 to realize 2-D code area positioning (Z-xing code). This article is mainly used for the summary of the author's own study, and the code part is posted temporarily, and the detailed details of the algorithm will be supplemented later.

Activity class Java File


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 The callback function after the class library is loaded and initialized successfully, so we don't do anything here  
 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{ 
 // We're in SurfaceView When creating, it is necessary to open the camera and set the preview framing place SurfaceView Set the parameters of taking pictures, start preview framing and other operations  
  @Override 
  public void surfaceCreated(SurfaceHolder holder) { 
   try { 
    camera = Camera.open();// Turn on the camera  
    camera.setPreviewDisplay(picSV.getHolder());// Settings picSV To preview and framing  
    Parameters params = camera.getParameters();// Get the parameters of the camera  
    params.setPictureSize(800, 480);// Set the size of the photo to 800*480 
    params.setPreviewSize(800, 480);// Set the size of preview framing to 800*480 
    params.setFlashMode("auto");// Turn on the flash  
    params.setJpegQuality(50);// Set the picture quality to 50   
    camera.setParameters(params);// Set the above parameters as camera parameters  
    camera.startPreview(); 
   } 
   catch (IOException e) {    // Start previewing and framing, and then we can take pictures  
    e.printStackTrace(); 
   } 
  } 
  
  @Override 
  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
  } 
  
  @Override 
  public void surfaceDestroyed(SurfaceHolder holder) { 
   // When SurfaceView When destroying, we do stop preview, release camera, garbage collection and so on  
   camera.stopPreview(); 
   camera.release(); 
   camera = null; 
  } 
 } 
 
 public void takepic(View v){ 
  // Before we start taking pictures, realize auto-focus  
  camera.autoFocus(new MyAutoFocusCallback()); 
 } 
 
 private class MyAutoFocusCallback implements AutoFocusCallback{ 
  @Override 
  public void onAutoFocus(boolean success, Camera camera) { 
   // Start taking pictures  
   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(); 
  // Pass OpenCV Engine service loads and initializes OpenCV Class library, so-called OpenCV The engine service is  
  //OpenCV_2.4.3.2_Manager_2.4_*.apk Package that exists in the OpenCV Installation package's apk In the directory  
  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(); 
   //2 Valuation plus contour finding  
   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"; 
   // Contour drawing  
   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(); 
   }    
  } 
 }; 
} 

File 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 file


<resources> 
 <string name="app_name">Code</string> 
 <string name="desc">Take picture button</string> 
</resources> 

style. xml file (theoretically, it can be generated automatically. If the content of automatic generation is wrong, please refer to it)


<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 file


<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> 

Related articles: