您好,登錄后才能下訂單哦!
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>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。