Android调用OpenCV2.4.10实现二维码区域定位
Android上使调用OpenCV2.4.10实现二维码区域定位(Z-xing码),该文章主要用于笔者自己学习中的总结,暂贴出代码部分,待以后有时间再补充算法的详细细节。
ActivityclassJava文件
packagecn.hjq.android_capture;
importjava.io.BufferedWriter;
importjava.io.File;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.OutputStreamWriter;
importjava.util.ArrayList;
importjava.util.List;
importorg.opencv.android.BaseLoaderCallback;
importorg.opencv.android.LoaderCallbackInterface;
importorg.opencv.android.OpenCVLoader;
importorg.opencv.core.*;
importorg.opencv.highgui.*;
importorg.opencv.imgproc.*;
importorg.opencv.utils.Converters;
importandroid.graphics.Bitmap;
importandroid.graphics.BitmapFactory;
importandroid.graphics.Matrix;
importandroid.hardware.Camera;
importandroid.hardware.Camera.AutoFocusCallback;
importandroid.hardware.Camera.Parameters;
importandroid.hardware.Camera.PictureCallback;
importandroid.os.Bundle;
importandroid.os.Environment;
importandroid.os.Handler;
importandroid.app.Activity;
importandroid.content.pm.ActivityInfo;
importandroid.view.MotionEvent;
importandroid.view.SurfaceHolder;
importandroid.view.SurfaceHolder.Callback;
importandroid.view.SurfaceView;
importandroid.view.View;
publicclasscaptureextendsActivity{
privateSurfaceViewpicSV;
privateCameracamera;
privateStringstrPicPath;
//OpenCV类库加载并初始化成功后的回调函数,在此我们不进行任何操作
privateBaseLoaderCallbackmLoaderCallback=newBaseLoaderCallback(this){
@Override
publicvoidonManagerConnected(intstatus){
switch(status){
caseLoaderCallbackInterface.SUCCESS:{
}break;
default:{
super.onManagerConnected(status);
}break;
}
}
};
@SuppressWarnings("deprecation")
@Override
protectedvoidonCreate(BundlesavedInstanceState){
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(newMyCallback());
}
privateclassMyCallbackimplementsCallback{
//我们在SurfaceView创建的时候就要进行打开摄像头、设置预览取景所在的SurfaceView、设置拍照的参数、开启预览取景等操作
@Override
publicvoidsurfaceCreated(SurfaceHolderholder){
try{
camera=Camera.open();//打开摄像头
camera.setPreviewDisplay(picSV.getHolder());//设置picSV来进行预览取景
Parametersparams=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(IOExceptione){//开始预览取景,然后我们就可以拍照了
e.printStackTrace();
}
}
@Override
publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,intheight){
}
@Override
publicvoidsurfaceDestroyed(SurfaceHolderholder){
//当SurfaceView销毁时,我们进行停止预览、释放摄像机、垃圾回收等工作
camera.stopPreview();
camera.release();
camera=null;
}
}
publicvoidtakepic(Viewv){
//在我们开始拍照前,实现自动对焦
camera.autoFocus(newMyAutoFocusCallback());
}
privateclassMyAutoFocusCallbackimplementsAutoFocusCallback{
@Override
publicvoidonAutoFocus(booleansuccess,Cameracamera){
//开始拍照
camera.takePicture(null,null,null,newMyPictureCallback());
}
}
privateclassMyPictureCallbackimplementsPictureCallback{
@Override
publicvoidonPictureTaken(byte[]data,Cameracamera){
try{
Bitmapbitmap=BitmapFactory.decodeByteArray(data,0,data.length);
Matrixmatrix=newMatrix();
matrix.preRotate(90);
bitmap=Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),
bitmap.getHeight(),matrix,true);
strPicPath=
Environment.getExternalStorageDirectory()+"/1Zxing/"+System.currentTimeMillis()+".jpg";
FileOutputStreamfos=newFileOutputStream(strPicPath);
bitmap.compress(Bitmap.CompressFormat.PNG,100,fos);
fos.close();
HandlermHandler=newHandler();
mHandler.post(mRunnable);
camera.startPreview();
}
catch(Exceptione){
e.printStackTrace();
}
}
}
publicbooleanonTouchEvent(MotionEventevent)
{
intAction=event.getAction();
if(1==Action){
camera.autoFocus(newMyAutoFocusCallback1());
}
returntrue;
}
privateclassMyAutoFocusCallback1implementsAutoFocusCallback{
@Override
publicvoidonAutoFocus(booleansuccess,Cameracamera){
}
}
@Override
publicvoidonResume(){
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);
}
RunnablemRunnable=newRunnable(){
publicvoidrun(){
Listcontours=newArrayList();
StringstrMissingTime=null;
MatsrcColor=newMat(),srcColorResize=newMat();
MatsrcGray=newMat(),srcGrayResize=newMat(),srcGrayResizeThresh=newMat();
srcGray=Highgui.imread(strPicPath,0);
srcColor=Highgui.imread(strPicPath,1);
Imgproc.resize(srcGray,srcGrayResize,newSize(srcGray.cols()*0.2,srcGray.rows()*0.2));
Imgproc.resize(srcColor,srcColorResize,newSize(srcGray.cols()*0.2,srcGray.rows()*0.2));
longstart=System.currentTimeMillis();
//二值化加轮廓寻找
Imgproc.adaptiveThreshold(srcGrayResize,srcGrayResizeThresh,255,
Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,
Imgproc.THRESH_BINARY,35,5);
Imgproc.findContours(srcGrayResizeThresh,contours,newMat(),
Imgproc.RETR_LIST,Imgproc.CHAIN_APPROX_NONE);
longend=System.currentTimeMillis();
strMissingTime=String.valueOf(end-start);
strMissingTime=strMissingTime+"\r";
//轮廓绘制
for(inti=contours.size()-1;i>=0;i--)
{
MatOfPoint2fNewMtx=newMatOfPoint2f(contours.get(i).toArray());
RotatedRectrotRect=Imgproc.minAreaRect(NewMtx);
Pointvertices[]=newPoint[4];
rotRect.points(vertices);
ListrectArea=newArrayList();
for(intn=0;n<4;n++)
{
Pointtemp=newPoint();
temp.x=vertices[n].x;
temp.y=vertices[n].y;
rectArea.add(temp);
}
MatrectMat=Converters.vector_Point_to_Mat(rectArea);
doubleminRectArea=Imgproc.contourArea(rectMat);
Pointcenter=newPoint();
floatradius[]={0};
Imgproc.minEnclosingCircle(NewMtx,center,radius);
if(
Imgproc.contourArea(contours.get(i))<300||
Imgproc.contourArea(contours.get(i))>3000
||minRectArea
layout.xml文件
string.xml文件
Code
Takepicturebutton
style.xml文件(理论上是可以自动生成,若自动生成内容有错,可以参考)
true
true
AndroidManifest.xml文件
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。