博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android学习——在Android中使用OpenCV的第一个程序
阅读量:6906 次
发布时间:2019-06-27

本文共 14248 字,大约阅读时间需要 47 分钟。

刚開始学习Android,因为之前比較熟悉OpenCV,于是就想先在Android上执行OpenCV试试

===================================================================================

1.环境配置

  • JDK
  • Eclipse
  • ADT
  • CDT
  • Android SDK
  • Android NDK
  • cygwin
  • OpenCV for Android 2.4.9

这部分网上非常多。我就不再赘述了,能够參考:

2.开发准备

两点注意

  • 新版安装SDK文件一開始有两个XML文件,activity_main.xml和fragment_main.xml:不习惯的能够这样处理:
删除fragment_main.xml整个文件对activity_main.xml,删除里面的内容。然后切换到Graphy Layout,放入一个LinearLayout就能够对MainActivity.java。能够删除部分的内容,再把MainActivity extends ActionBarActivity 改为MainActivity extends Activity ( 关于activity_main.xml与fragment_main.xml的问题參看: )
  • 引入OpenCV库
            Package Explorer中选择项目,单击右键在弹出菜单中选择Properties,然后在弹出的Properties窗体中左側选择Android。然后点击右下方的Addbutton,选择OpenCV Library 2.4.9并点击OK。操作完毕后,会将OpenCV类库加入到GrayProcess的Android Dependencies中
3.编敲代码
目的是实现通过OpenCV for Android实现摄像头採集图像的处理。并通过SurfaceView显示在手机屏幕上
OpenCV的Android库将Android自身的相机相关的库进行了封装。用起来十分方便
  • CameraBridgeViewBase .enableView()
  • SurfaceView is available
    • CameraBridgeViewBase  .setVisibility(SurfaceView.Visiable)
    • CameraBridgeViewBase  .setCvCameraViewListener(this)
就能够使用回调函数
  • onCameraViewStarted 
  • onCameraViewStopped
图像处理写在
  • public Mat onCameraFrame(CvCameraViewFrame inputFrame)
Java文件:
public class MainActivity extends Activity implements CvCameraViewListener2 {    private static final String TAG = "OCVSample::Activity";    private CameraBridgeViewBase mOpenCvCameraView;    private boolean mIsJavaCamera = true;    private MenuItem mItemSwitchCamera = null;    private Mat mRgba;    private Button mBtn = null;    private boolean	 isProcess = false;//建立连接    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {        @Override        public void onManagerConnected(int status) {            switch (status) {                case LoaderCallbackInterface.SUCCESS:                {                    Log.i(TAG, "OpenCV loaded successfully");                    mOpenCvCameraView.enableView();                } break;                default:                {                    super.onManagerConnected(status);                } break;            }        }    };//构造函数    public MainActivity() {        Log.i(TAG, "Instantiated new " + this.getClass());    }    /** Called when the activity is first created. *///onCreate函数    @Override    public void onCreate(Bundle savedInstanceState) {        Log.i(TAG, "called onCreate");        super.onCreate(savedInstanceState);        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);        setContentView(R.layout.activity_main);//        if (mIsJavaCamera)            mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);        else            mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_native_surface_view);        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);               mOpenCvCameraView.setCvCameraViewListener(this);               mBtn = (Button) findViewById(R.id.buttonGray);  mBtn.setOnClickListener(new View.OnClickListener(){   @Override      public void onClick(View v) {    isProcess = !isProcess;      }  });    }    @Override    public void onPause()    {        super.onPause();        if (mOpenCvCameraView != null)            mOpenCvCameraView.disableView();    }    @Override    public void onResume()    {        super.onResume();        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this, mLoaderCallback);    }    public void onDestroy() {        super.onDestroy();        if (mOpenCvCameraView != null)            mOpenCvCameraView.disableView();    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        Log.i(TAG, "called onCreateOptionsMenu");        mItemSwitchCamera = menu.add("Toggle Native/Java camera");        return true;    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        String toastMesage = new String();        Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);        if (item == mItemSwitchCamera) {            mOpenCvCameraView.setVisibility(SurfaceView.GONE);            mIsJavaCamera = !mIsJavaCamera;            if (mIsJavaCamera) {                mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);                toastMesage = "Java Camera";            } else {                mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_native_surface_view);                toastMesage = "Native Camera";            }            mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);            mOpenCvCameraView.setCvCameraViewListener(this);            mOpenCvCameraView.enableView();            Toast toast = Toast.makeText(this, toastMesage, Toast.LENGTH_LONG);            toast.show();        }        return true;    }    public void onCameraViewStarted(int width, int height) {     mRgba = new Mat(height, width, CvType.CV_8UC4);    }    public void onCameraViewStopped() {     mRgba.release();    }    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {     if(isProcess)      Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA, 4);     else       mRgba = inputFrame.rgba();     return mRgba;    }}
Manifest文件:
需增加相机使用权限
注意:一般Android摄像头採集的图像方向不正确
在纯Android的开发环境中,一般採用
mCamera.setDisplayOrientation(90);
在OpenCV for Android的开发中,在
Manifest文件里增加
android:screenOrientation="landscape" android:configChanges="keyboardHidden|orientation"
完整的Manifest文件
layout文件
activity_main.xml
原图:
灰度图:
Java程序2:
分别完毕了
  1. 原图
  2. 灰度图
  3. Canny边缘检測
  4. Hist 直方图计算
  5. Sobel 边缘检測
  6. SEPIA(色调变换)为每个数组元素运行一个矩阵变换
  7. ZOOM 放大镜
  8. PIXELIZE 像素化
  9. POSTERIZE 多色调分色印
package com.example.camera03;import java.util.Arrays;import org.opencv.android.BaseLoaderCallback;import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;import org.opencv.android.LoaderCallbackInterface;import org.opencv.android.OpenCVLoader;import org.opencv.core.Core;import org.opencv.core.CvType;import org.opencv.core.Mat;import org.opencv.core.MatOfFloat;import org.opencv.core.MatOfInt;import org.opencv.core.Point;import org.opencv.core.Scalar;import org.opencv.core.Size;import org.opencv.imgproc.Imgproc;import org.opencv.android.CameraBridgeViewBase;import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.SurfaceView;import android.view.View;import android.view.WindowManager;import android.widget.Button;import android.widget.Toast;public class MainActivity extends Activity implements CvCameraViewListener2 {    private static final String TAG = "OCVSample::Activity";    private CameraBridgeViewBase mOpenCvCameraView;    private boolean mIsJavaCamera = true;    private MenuItem mItemSwitchCamera = null;    private Mat mRgba;    private Mat mGray;    private Mat mTmp;        private Size mSize0;    private Mat mIntermediateMat;    private MatOfInt mChannels[];    private MatOfInt mHistSize;    private int mHistSizeNum = 25;    private Mat mMat0;    private float[] mBuff;    private MatOfFloat mRanges;    private Point mP1;    private Point mP2;    private Scalar mColorsRGB[];    private Scalar mColorsHue[];    private Scalar mWhilte;    private Mat mSepiaKernel;    private Button mBtn = null;    private int	 mProcessMethod = 0;            private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {        @Override        public void onManagerConnected(int status) {            switch (status) {                case LoaderCallbackInterface.SUCCESS:                {                    Log.i(TAG, "OpenCV loaded successfully");                    mOpenCvCameraView.enableView();                } break;                default:                {                    super.onManagerConnected(status);                } break;            }        }    };    public MainActivity() {        Log.i(TAG, "Instantiated new " + this.getClass());    }    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        Log.i(TAG, "called onCreate");        super.onCreate(savedInstanceState);        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);        setContentView(R.layout.activity_main);        if (mIsJavaCamera)            mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);        else            mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_native_surface_view);        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);                mOpenCvCameraView.setCvCameraViewListener(this);                mBtn = (Button) findViewById(R.id.buttonGray);  mBtn.setOnClickListener(new View.OnClickListener(){   @Override        public void onClick(View v) {    mProcessMethod++;    if(mProcessMethod>8) mProcessMethod=0;      }    });    }    @Override    public void onPause()    {        super.onPause();        if (mOpenCvCameraView != null)            mOpenCvCameraView.disableView();    }    @Override    public void onResume()    {        super.onResume();        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this, mLoaderCallback);    }    public void onDestroy() {        super.onDestroy();        if (mOpenCvCameraView != null)            mOpenCvCameraView.disableView();    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        Log.i(TAG, "called onCreateOptionsMenu");        mItemSwitchCamera = menu.add("Toggle Native/Java camera");        return true;    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        String toastMesage = new String();        Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);        if (item == mItemSwitchCamera) {            mOpenCvCameraView.setVisibility(SurfaceView.GONE);            mIsJavaCamera = !mIsJavaCamera;            if (mIsJavaCamera) {                mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);                toastMesage = "Java Camera";            } else {                mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_native_surface_view);                toastMesage = "Native Camera";            }            mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);            mOpenCvCameraView.setCvCameraViewListener(this);            mOpenCvCameraView.enableView();            Toast toast = Toast.makeText(this, toastMesage, Toast.LENGTH_LONG);            toast.show();        }        return true;    }    public void onCameraViewStarted(int width, int height) {     mRgba = new Mat(height, width, CvType.CV_8UC4);     mGray = new Mat(height, width, CvType.CV_8UC1);     mTmp = new Mat(height, width, CvType.CV_8UC4);           mIntermediateMat = new Mat();         mSize0 = new Size();         mChannels = new MatOfInt[] { new MatOfInt(0), new MatOfInt(1), new MatOfInt(2) };         mBuff = new float[mHistSizeNum];         mHistSize = new MatOfInt(mHistSizeNum);         mRanges = new MatOfFloat(0f, 256f);         mMat0 = new Mat();         mColorsRGB = new Scalar[] { new Scalar(200, 0, 0, 255), new Scalar(0, 200, 0, 255), new Scalar(0, 0, 200, 255) };         mColorsHue = new Scalar[] {                 new Scalar(255, 0, 0, 255), new Scalar(255, 60, 0, 255), new Scalar(255, 120, 0, 255), new Scalar(255, 180, 0, 255), new Scalar(255, 240, 0, 255),                 new Scalar(215, 213, 0, 255), new Scalar(150, 255, 0, 255), new Scalar(85, 255, 0, 255), new Scalar(20, 255, 0, 255), new Scalar(0, 255, 30, 255),                 new Scalar(0, 255, 85, 255), new Scalar(0, 255, 150, 255), new Scalar(0, 255, 215, 255), new Scalar(0, 234, 255, 255), new Scalar(0, 170, 255, 255),                 new Scalar(0, 120, 255, 255), new Scalar(0, 60, 255, 255), new Scalar(0, 0, 255, 255), new Scalar(64, 0, 255, 255), new Scalar(120, 0, 255, 255),                 new Scalar(180, 0, 255, 255), new Scalar(255, 0, 255, 255), new Scalar(255, 0, 215, 255), new Scalar(255, 0, 85, 255), new Scalar(255, 0, 0, 255)         };         mWhilte = Scalar.all(255);         mP1 = new Point();         mP2 = new Point();         // Fill sepia kernel         mSepiaKernel = new Mat(4, 4, CvType.CV_32F);         mSepiaKernel.put(0, 0, /* R */0.189f, 0.769f, 0.393f, 0f);         mSepiaKernel.put(1, 0, /* G */0.168f, 0.686f, 0.349f, 0f);         mSepiaKernel.put(2, 0, /* B */0.131f, 0.534f, 0.272f, 0f);         mSepiaKernel.put(3, 0, /* A */0.000f, 0.000f, 0.000f, 1f);    }    public void onCameraViewStopped() {     mRgba.release();     mGray.release();     mTmp.release();    }    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {          mRgba = inputFrame.rgba();     Size sizeRgba = mRgba.size();     int rows = (int) sizeRgba.height;        int cols = (int) sizeRgba.width;        Mat rgbaInnerWindow;                int left = cols / 8;        int top = rows / 8;        int width = cols * 3 / 4;        int height = rows * 3 / 4;        //灰度图     if(mProcessMethod==1)      Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA, 4);     //Canny边缘检測     else if(mProcessMethod==2)     {      mRgba = inputFrame.rgba();      Imgproc.Canny(inputFrame.gray(), mTmp, 80, 100);      Imgproc.cvtColor(mTmp, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);     }     //Hist     else if(mProcessMethod==3)     {       Mat hist = new Mat();             int thikness = (int) (sizeRgba.width / (mHistSizeNum + 10) / 5);             if(thikness > 5) thikness = 5;             int offset = (int) ((sizeRgba.width - (5*mHistSizeNum + 4*10)*thikness)/2);               // RGB             for(int c=0; c<3; c++) {                 Imgproc.calcHist(Arrays.asList(mRgba), mChannels[c], mMat0, hist, mHistSize, mRanges);                 Core.normalize(hist, hist, sizeRgba.height/2, 0, Core.NORM_INF);                 hist.get(0, 0, mBuff);                 for(int h=0; h
  • 原图
  • 灰度图
  • Canny边缘检測
  • Hist 直方图计算
  • Sobel 边缘检測
  • SEPIA(色调变换)为每个数组元素运行一个矩阵变换
  • ZOOM 放大镜
  • PIXELIZE 像素化
  • POSTERIZE 多色调分色印

你可能感兴趣的文章
用createObjectURL实现本地图片预览
查看>>
【物联网】——智慧交通
查看>>
第十五课时: 响应式布局
查看>>
如何在1到100的整数数组上找到缺失的数字
查看>>
webToImage (网页转图片)模块试用分享
查看>>
前端实用知识
查看>>
90. Subsets II
查看>>
前嗅ForeSpider教程:如何创建新任务
查看>>
大厂高级前端面试题答案
查看>>
javascript动态合并纵向单元格
查看>>
JavaScript 是如何工作的:模块的构建以及对应的打包工具
查看>>
Spring Boot 2.1.2 & Spring Cloud Greenwich 升级记录
查看>>
leetcode378. Kth Smallest Element in a Sorted Matrix
查看>>
DOM 元素中的焦点管理
查看>>
个人博客四|注册登录退出功能后台开发
查看>>
如何更优雅地切换Git分支
查看>>
Spring AOP(一) AOP基本概念
查看>>
Python之时间和日期使用小结
查看>>
XXL-RPC v1.3.2,分布式服务框架
查看>>
【React深入】setState的执行机制
查看>>