Android調(diào)用OpenCV2.4.10實(shí)現(xiàn)二維碼區(qū)域定位
Android上使調(diào)用OpenCV 2.4.10 實(shí)現(xiàn)二維碼區(qū)域定位(Z-xing 碼),該文章主要用于筆者自己學(xué)習(xí)中的總結(jié),暫貼出代碼部分,待以后有時(shí)間再補(bǔ)充算法的詳細(xì)細(xì)節(jié)。
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類庫加載并初始化成功后的回調(diào)函數(shù),在此我們不進(jìn)行任何操作
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創(chuàng)建的時(shí)候就要進(jìn)行打開攝像頭、設(shè)置預(yù)覽取景所在的SurfaceView、設(shè)置拍照的參數(shù)、開啟預(yù)覽取景等操作
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();//打開攝像頭
camera.setPreviewDisplay(picSV.getHolder());//設(shè)置picSV來進(jìn)行預(yù)覽取景
Parameters params = camera.getParameters();//獲取照相機(jī)的參數(shù)
params.setPictureSize(800, 480);//設(shè)置照片的大小為800*480
params.setPreviewSize(800, 480);//設(shè)置預(yù)覽取景的大小為800*480
params.setFlashMode("auto");//開啟閃光燈
params.setJpegQuality(50);//設(shè)置圖片質(zhì)量為50
camera.setParameters(params);//設(shè)置以上參數(shù)為照相機(jī)的參數(shù)
camera.startPreview();
}
catch (IOException e) { //開始預(yù)覽取景,然后我們就可以拍照了
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//當(dāng)SurfaceView銷毀時(shí),我們進(jìn)行停止預(yù)覽、釋放攝像機(jī)、垃圾回收等工作
camera.stopPreview();
camera.release();
camera = null;
}
}
public void takepic(View v){
//在我們開始拍照前,實(shí)現(xiàn)自動對焦
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引擎服務(wù)加載并初始化OpenCV類庫,所謂OpenCV引擎服務(wù)即是
//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 文件(理論上是可以自動生成,若自動生成內(nèi)容有錯(cuò),可以參考)
<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>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android 超簡易Zxing框架 生成二維碼+掃碼功能
- Android實(shí)現(xiàn)掃描和生成二維碼
- 超簡單Android集成華為HMS Scankit 掃碼SDK實(shí)現(xiàn)掃一掃二維碼
- Android實(shí)現(xiàn)掃描二維碼功能
- Android studio 實(shí)現(xiàn)手機(jī)掃描二維碼功能
- Android生成條形碼和二維碼功能
- Android如何實(shí)現(xiàn)掃描和生成二維碼
- Android掃描和生成二維碼
- Android zxing如何識別反轉(zhuǎn)二維碼詳解
- Android基于OpenCV實(shí)現(xiàn)QR二維碼檢測
相關(guān)文章
android LinearLayout 布局實(shí)例代碼
android LinearLayout 布局實(shí)例代碼,需要的朋友可以參考一下2013-04-04
Android編程獲取并設(shè)置Activity亮度的方法
這篇文章主要介紹了Android編程獲取并設(shè)置Activity亮度的方法,涉及Android針對屏幕亮度的相關(guān)操作技巧,需要的朋友可以參考下2015-12-12
Flutter應(yīng)用框架搭建實(shí)現(xiàn)屏幕適配方案詳解
移動設(shè)備多樣性,特別是Android的碎片化嚴(yán)重,存在各種各樣的分辨率,flutter跨平臺開發(fā)又需要同時(shí)支持Android和IOS,為盡可能的還原設(shè)計(jì)圖效果提升用戶的體驗(yàn),根據(jù)設(shè)計(jì)稿設(shè)計(jì)屏幕ui的時(shí)候我們需要考慮到屏幕適配的問題2022-11-11
取消Android Studio項(xiàng)目與SVN關(guān)聯(lián)的方法
今天小編就為大家分享一篇關(guān)于取消Android Studio項(xiàng)目與SVN關(guān)聯(lián)的方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12
Android View事件分發(fā)和消費(fèi)源碼簡單理解
這篇文章主要介紹了Android View事件分發(fā)和消費(fèi)源碼簡單理解的相關(guān)資料,需要的朋友可以參考下2017-07-07
基于Android實(shí)現(xiàn)轉(zhuǎn)盤按鈕代碼
這篇文章主要介紹了基于Android實(shí)現(xiàn)轉(zhuǎn)盤按鈕代碼的相關(guān)資料,需要的朋友可以參考下2015-12-12
Android編程之短信竊聽器實(shí)現(xiàn)方法
這篇文章主要介紹了Android編程之短信竊聽器實(shí)現(xiàn)方法,以實(shí)例形式較為詳細(xì)的分析了Android編程實(shí)現(xiàn)竊聽器的具體步驟與實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11

