zoukankan      html  css  js  c++  java
  • android 与 opencv 关于前后置相机 与 javaCameraView NativeCameraView

    代码出处:http://opencv.org/ 的 OpenCV for Android version 2.4.5

    .../OpenCV-2.4.5-android-sdk/samples/face-detection/


    # 1 如何让opencv使用前后相机?

      玩opencv4Android的sample时发现,sample仅做了后置的相机的识别。

      那么如何使用让他可以对frontCamera进行处理呢?

      于是google发现了这个:http://answers.opencv.org/question/4226/how-i-use-front-camera-with-new-opencv-243-for/  

    答案提出了通过修改openCVlibrary的库参数来达到使用frontCamera的目的。

      再那个2.43的环境下只能写死,或者自己再这块重写opencv的Library。

      于是准备改时意外发现了2.45与2.43不同,多了个参数

     --> 2.43

        private boolean initializeCamera(int width, int height) {
            synchronized (this) {
                // +1 表示使用frontCamera   +0 表示使用backCamera
                mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID +1);
    
                if (mCamera == null)
                    return false;
    
                if (mCamera.isOpened() == false)
                    return false;
    ....

     --> 2.45

        private boolean initializeCamera(int width, int height) {
            synchronized (this) {
            //  多了mCameraIndex参数 看来此参数是用来改变 [front,back]{1}
                if (mCameraIndex == -1)
                    mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
                else
                    mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID + mCameraIndex);
    
                if (mCamera == null)
                    return false;
    
                if (mCamera.isOpened() == false)
                    return false;

      有没有发现2.45的版本多了个mCameraIndex参数。然后发现mCameraIndex是写在CameraBridgeViewBase的类里的,而CameraBridgeViewBase类是 JavaCameraView 和 NativeCameraView 的父类。

      我们知道如果要让屏幕出现照相机的话必定是在屏幕里放置一个layout,然后再layout里布局各种参数和放置的位置。

    实例化layout:

    mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.fd_activity_surface_view);

    由上面我们知道获取的实例是CameraBridgeViewBase,所以推测一定是把上面的mCameraIndex的参数写在layout里。

    搜了下官方文档,确实有写:http://docs.opencv.org/trunk/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.html?highlight=javacameraview

    opencv:show_fps="true" andopencv:camera_id="any" options enable FPS message and allow to use any camera on device. Application tries to use back camera first.

    看到这句话 心里小小的激动了下。。。

    接下来要实现切换前后镜头的思路就是需要按按钮时触发切换整个layout(因为前后参数是写在layout里的),切换layout方法,http://www.pocketdigi.com/20110509/269.html


    --------2013-5-18--add----------------------- 

      上面的思路是通过切换整个layout来达到切屏的目的,还可以通过更换layout上的view,来达到同样的目的。启发自: OpenCV Tutorial 1 - Camera Preview

    写一个layout,里面包含2个view:

    <LinearLayout 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" />
    
    </LinearLayout>

    然后再Activity里直接修改 CameraBridgeViewBase 就行:

            if (mIsJavaCamera)
                mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);
            else
                mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_native_surface_view);
            

    意外发现

      按照sample提供的切换javaCamera 和 NativeCamera 的方法依样画葫芦的加了切换前后镜头的方法。却发现点击Menuitem却且不了前置镜头。 后来发现是代码的bug。。。

     1 private int mDetectorType;
     2 ...
     3         else if (item == mItemType) {
     4             mDetectorType = (mDetectorType + 1) % mDetectorName.length;
     5             item.setTitle(mDetectorName[mDetectorType]);
     6                         // 此处。。
     7             setDetectorType(mDetectorType);
     8 ...
     9 
    10     private void setDetectorType(int type) {
    11         if (mDetectorType != type) {
    12             mDetectorType = type;
    13 
    14             if (type == NATIVE_DETECTOR) {
    15                 Log.i(TAG, "Detection Based Tracker enabled");
    16                 mNativeDetector.start();
    17             } else {
    18                 Log.i(TAG, "Cascade detector enabled");
    19                 mNativeDetector.stop();
    20             }
    21         }
    22     }
    mDetectorType是个全局变量调用函数时给他的参数也是mDetectorType,再setDetector函数里进行了
    if (mDetectorType != type (即 mDetectorType) ) {...}

    哎,永远进步了if了。。。

    我的解决方法: 改成临时变量就行。。

                int tmpDetectorType = (mDetectorType + 1) % mDetectorName.length;
                item.setTitle(mDetectorName[tmpDetectorType]);
                setDetectorType(tmpDetectorType);

    狠狠插入 - 关于openCV Library是什么?JavaCameraView和NativeCameraView的区别是什么?

      openCV Library 其实就是个 c++实现的openCV库的 java接口,通过jni调用。

      从package org.opencv.android;可以看到,initOpenCV的时候先获取library list,大概是各个cpp文件。

            Log.d(TAG, "Trying to get library list");
    
            try
            {
                System.loadLibrary("opencv_info");
                libs = getLibraryList();
            }

      然后 全部无脑载入内存

        private static boolean initOpenCVLibs(String Libs)
        {
            Log.d(TAG, "Trying to init OpenCV libs");
    
            boolean result = true;
    
            if ((null != Libs) && (Libs.length() != 0))
            {
                Log.d(TAG, "Trying to load libs by dependency list");
                StringTokenizer splitter = new StringTokenizer(Libs, ";");
                while(splitter.hasMoreTokens())
                {
                    result &= loadLibrary(splitter.nextToken());
                }
            }
        ...

     如果自己写的opencv c++程序编译后,通过此方法载入:

        private static boolean loadLibrary(String Name)
        {
            boolean result = true;
    
            Log.d(TAG, "Trying to load library " + Name);
            try
            {
                System.loadLibrary(Name);
                Log.d(TAG, "OpenCV libs init was ok!");
            }
            catch(UnsatisfiedLinkError e)
            {
                Log.d(TAG, "Cannot load library \"" + Name + "\"");
                e.printStackTrace();
                result &= false;
            }
    
            return result;
        }

    JavaCameraView和NativeCameraView的区别

    之前有过各种猜测直到看到了这个。。。 http://docs.opencv.org/trunk/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.html?highlight=javacameraview

    First of all we create our application view using xml layout. Our layout consists of the only one full screen component of class org.opencv.android.JavaCameraView. This class is implemented inside OpenCV library. It is inherited from CameraBridgeViewBase, that extends SurfaceView and uses standard Android camera API. Alternatively you can use org.opencv.android.NativeCameraView class, that implements the same interface, but uses VideoCapture class as camera access back-end.

    而在facedetect的sample里的

        private CascadeClassifier mJavaDetector;
        private DetectionBasedTracker mNativeDetector;

    让我混乱了很久,我开始以为他们分别代表了javaCameraView和NativeCameraView,其实他们都是基于javaCameraView,(是否是基于javaCameraView主要看他的layout里给他配的是Java还是Native,上面有提到),

    mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.fd_activity_surface_view);

    而这里的javaDetector表示使用android的sdk提供的借口来调用opencv,而NativeDector表示调用自己写得本地cpp文件,本地cpp import相应的头文件,并调用opencv借口,在这个sample里其实他们都是调用同一个opencv接口。

     待续。。

    这是签名?
  • 相关阅读:
    XAML
    诺基亚Lumia 800越狱教程
    Windows Phone常用控件
    Windows Phone数据存储
    Silverlight自定义鼠标
    [silverlight] silverlight3新增功能1:三维效果(透视转换)
    [silverlight] silverlight3新增功能2:WriteableBitmap
    另一种方法实现silverlight图片局部放大效果
    [Silverlight]简单实现DataGrid使用CheckBox选择行
    好用的模糊搜索下拉提示
  • 原文地址:https://www.cnblogs.com/Lelpuchcr/p/3080703.html
Copyright © 2011-2022 走看看