刚开始学习Android,由于之前比较熟悉OpenCV,于是就想先在Android上运行OpenCV试试

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

1.环境配置

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

这部分网上很多,我就不再赘述了,可以参考:http://blog.csdn.net/pwh0996/article/details/8957764


2.开发准备

两点注意

  • 新版安装SDK文件一开始有两个XML文件,activity_main.xml和fragment_main.xml:不习惯的可以这样处理:
  1. 删除fragment_main.xml整个文件
  2. 对activity_main.xml,删除里面的内容。然后切换到GraphyLayout,放入一个LinearLayout就可以
  3. 对MainActivity.java,可以删除部分的内容,再把MainActivityextendsActionBarActivity改为MainActivityextendsActivity
  4. (关于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文件:
需加入相机使用权限
<uses-permission android:name="android.permission.CAMERA"/> 
注意:一般Android摄像头采集的图像方向不对 在纯Android的开发环境中,一般采用
mCamera.setDisplayOrientation(90);
在OpenCV for Android的开发中,在 Manifest文件中加入
android:screenOrientation="landscape" android:configChanges="keyboardHidden|orientation"

完整的Manifest文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.camera03" android:versionCode="1" android:versionName="1.0" > <supports-screens android:resizeable="true" android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" /> <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.CAMERA"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > <activity android:name="com.example.camera03.MainActivity" android:label="@string/app_name" android:screenOrientation="landscape" android:configChanges="keyboardHidden|orientation"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 

layout文件 activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:opencv="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <org.opencv.android.JavaCameraView        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:visibility="gone"        android:id="@+id/tutorial1_activity_java_surface_view"        opencv:show_fps="true"        opencv:camera_id="any" />    <org.opencv.android.NativeCameraView        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:visibility="gone"        android:id="@+id/tutorial1_activity_native_surface_view"        opencv:show_fps="true"        opencv:camera_id="any" />    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="match_parent" >        <Button            android:id="@+id/buttonGray"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:layout_centerHorizontal="true"            android:text="@string/buttonGray" />    </RelativeLayout></FrameLayout>



原图
灰度图:

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<mHistSizeNum; h++) {                     mP1.x = mP2.x = offset + (c * (mHistSizeNum + 10) + h) * thikness;                     mP1.y = sizeRgba.height-1;                     mP2.y = mP1.y - 2 - (int)mBuff[h];                     Core.line(mRgba, mP1, mP2, mColorsRGB[c], thikness);                 }             }             // Value and Hue             Imgproc.cvtColor(mRgba, mTmp, Imgproc.COLOR_RGB2HSV_FULL);             // Value             Imgproc.calcHist(Arrays.asList(mTmp), mChannels[2], 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<mHistSizeNum; h++) {                 mP1.x = mP2.x = offset + (3 * (mHistSizeNum + 10) + h) * thikness;                 mP1.y = sizeRgba.height-1;                 mP2.y = mP1.y - 2 - (int)mBuff[h];                 Core.line(mRgba, mP1, mP2, mWhilte, thikness);             }     }     //inner Window Sobel     else if(mProcessMethod==4)     {      Mat gray = inputFrame.gray();            Mat grayInnerWindow = gray.submat(top, top + height, left, left + width);            rgbaInnerWindow = mRgba.submat(top, top + height, left, left + width);            Imgproc.Sobel(grayInnerWindow, mIntermediateMat, CvType.CV_8U, 1, 1);            Core.convertScaleAbs(mIntermediateMat, mIntermediateMat, 10, 0);            Imgproc.cvtColor(mIntermediateMat, rgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4);            grayInnerWindow.release();            rgbaInnerWindow.release();     }     //SEPIA     else if(mProcessMethod==5)     {      rgbaInnerWindow = mRgba.submat(top, top + height, left, left + width);            Core.transform(rgbaInnerWindow, rgbaInnerWindow, mSepiaKernel);            rgbaInnerWindow.release();     }     //ZOOM     else if(mProcessMethod==6)     {      Mat zoomCorner = mRgba.submat(0, rows / 2 - rows / 10, 0, cols / 2 - cols / 10);            Mat mZoomWindow = mRgba.submat(rows / 2 - 9 * rows / 100, rows / 2 + 9 * rows / 100, cols / 2 - 9 * cols / 100, cols / 2 + 9 * cols / 100);            Imgproc.resize(mZoomWindow, zoomCorner, zoomCorner.size());            Size wsize = mZoomWindow.size();            Core.rectangle(mZoomWindow, new Point(1, 1), new Point(wsize.width - 2, wsize.height - 2), new Scalar(255, 0, 0, 255), 2);            zoomCorner.release();            mZoomWindow.release();     }     //PIXELIZE     else if(mProcessMethod==7)     {      rgbaInnerWindow = mRgba.submat(top, top + height, left, left + width);            Imgproc.resize(rgbaInnerWindow, mIntermediateMat, mSize0, 0.1, 0.1, Imgproc.INTER_NEAREST);            Imgproc.resize(mIntermediateMat, rgbaInnerWindow, rgbaInnerWindow.size(), 0., 0., Imgproc.INTER_NEAREST);            rgbaInnerWindow.release();     }     //POSTERIZE     else if(mProcessMethod==8)     {      rgbaInnerWindow = mRgba.submat(top, top + height, left, left + width);            Imgproc.Canny(rgbaInnerWindow, mIntermediateMat, 80, 90);            rgbaInnerWindow.setTo(new Scalar(0, 0, 0, 255), mIntermediateMat);            Core.convertScaleAbs(rgbaInnerWindow, mIntermediateMat, 1./16, 0);            Core.convertScaleAbs(mIntermediateMat, rgbaInnerWindow, 16, 0);            rgbaInnerWindow.release();     }     else      mRgba = inputFrame.rgba();     return mRgba;    }}
  • 原图

  • 灰度图

  • Canny边缘检测

  • Hist 直方图计算

  • Sobel 边缘检测

  • SEPIA(色调变换)为每一个数组元素执行一个矩阵变换

  • ZOOM 放大镜

  • PIXELIZE 像素化

  • POSTERIZE多色调分色印




更多相关文章

  1. cordova入门教程(五)给android apk签名
  2. Android组件的样式
  3. 2011.07.05(2)——— android PopupWindow
  4. Android内核的根文件系统
  5. Android文件存储
  6. android操作xml
  7. Android多媒体开发(5)————利用Android(安卓)AudioTrack播放mp3
  8. Android代码实现APK文件的安装与卸载
  9. android获取文件目录

随机推荐

  1. Android Studio开发APP常用方法(一)
  2. android TabActivity中onKeyDown无效问题
  3. Android:注册一个方向传感器的回调,能够让
  4. android 特殊用法琐碎二
  5. 初识Android之(一)-自定义标题栏控件
  6. android 通过php post 向mysql数据库写入
  7. Android(安卓)官方自带侧滑菜单DrawerLay
  8. Android FFmpeg 脚本编译静态库
  9. 简单几段代码实现窗口抖动
  10. gerrit 常用命令记录