Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android學習——在Android中使用OpenCV的第一個程序

Android學習——在Android中使用OpenCV的第一個程序

編輯:關於Android編程

剛開始學習Android,由於之前比較熟悉OpenCV,於是就想先在Android上運行OpenCV試試

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

1.環境配置

JDKEclipseADTCDTAndroid SDKAndroid NDKcygwinOpenCV for Android 2.4.9

這部分網上很多,我就不再贅述了,可以參考:http://blog.csdn.net/pwh0996/article/details/8957764


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的問題參看:http://bbs.csdn.net/topics/390740123) 引入OpenCV庫 Package Explorer中選擇項目,單擊右鍵在彈出菜單中選擇Properties,然後在彈出的Properties窗口中左側選擇Android,然後點擊右下方的Add按鈕,選擇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文件
           
           
          
           
           
           
          
           
           
           
           
          
           
           
           
           
          
           

          原圖: \
          灰度圖: vc28vMbL4zxsaT5Tb2JlbCCx39S1vOyy4jxsaT5TRVBJQaOoyau197Hku7ujqc6qw7/Su7j2yv3X6dSqy9jWtNDQ0ru49r7Y1fOx5Lu7PGxpPlpPT00gt8W08761PGxpPlBJWEVMSVpFIM/xy9i7rzxsaT5QT1NURVJJWkUgtuDJq7X3t9bJq9OhCgo8cHJlIGNsYXNzPQ=="brush:java;">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 多色調分色印




  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved