OpenCV4Android背景建模(MOG、MOG2)

來源:互聯網
上載者:User

標籤:屬性   自己   htm   tor   版本   ref   xxx   ado   system   

本文為作者原創,轉載請註明出處  ——負贔屭      很久以前的筆記了,分享給大家吧。。。OpenCV4Android中用於背景建模的類主要有:BackgroundSubtractor、BackgroundSubtractorMOG、BackgroundSubtractorMOG2、BackgroundSubtractorKNN,主要對使用方法做個總結。      借用OpenCV提供的API,Android編程可以實現比較豐富的視覺處理效果。經過多次嘗試,終於梳理出OpenCV背景建模在Android中的使用方法。BackgroundSubtractor的java API在OpenCV2.x和3.x版本有較大區別,3.x提供了比較豐富的API介面,取消了2.4中的高斯背景建模1(BackgroundSubtractorMOG),保留了高斯背景建模2(BackgroundSubtractorMOG2),引入了KNN背景建模(BackgroundSubtractorKNN)。同時提供了很多訪問BackgroundSubtractor背景模型的屬性方法,例如getBackgroundImage等。廢話不多說,總結如下:      一、通過Java介面實現背景建模     無論在OpenCV2.x還是3.x,BackgroundSubtractor類都必須在幀迴圈處理之前定義,例如:給OpenCV內建的Tutorial2 常式增加一個BackgroundSubtractorMOG2類的前景偵測方法。      1、定義一個BackgroundSubtractorMOG2 對象,Tutorial2 常式對於用到的mat類對象定義為private全域變數,參照給出定義:
public class Tutorial2Activity extends Activity implements CvCameraViewListener2 {         ……  private Mat                    mRgba;  private Mat                    mIntermediateMat;  private Mat                    mGray;  private BackgroundSubtractorMOG2 mog2;

 

     2、mog2對象初始化,Tutorial2 常式在onCameraViewStarted方法中對mat對象進行初始化,參照執行:
public void onCameraViewStarted(int width, int height) {    mRgba = new Mat(height, width, CvType.CV_8UC4);    mIntermediateMat = new Mat(height, width, CvType.CV_8UC4);    mGray = new Mat(height, width, CvType.CV_8UC1);    mog2 = new BackgroundSubtractorMOG2();         //OpenCV2.x初始化方法    //mog2 = video.createBackgroundSubtractorMOG2();//OpenCV3.x初始化方法 }

  需要注意的是OpenCV2.x初始化BackgroundSubtractorMOG2對象是通過new來實現,但是在3.x版本中是通過mog2 = Video.createBackgroundSubtractorMOG2()來實現。

      3、執行背景建模,直接把常式中的canny方法改成BackgroundSubtractor:     
case BUTTON_GETBG:    mRgba = inputFrame.rgba();    bg2.apply(inputFrame.gray(),mIntermediateMat,0.01);//前景儲存在mIntermediateMat中    //bg2.getBackgroundImage(mBG);                     //OpenCV3.x提供擷取背景函數
  由於OpenCV2.x沒有提供getBackgroundImage方法,讓我們折騰折騰,通過jni給它實現一下:      二、通過jni實現背景建模     首先你得大致會jni,不在這裡展開講,推薦看一下http://www.cnblogs.com/linguanh/p/4624768.html,做好準備工作。      1、定義GetBGImage類繼承BackgroundSubtractorMOG2類,並定義其中的native方法:
/** * 因為OpenCV2.4中沒有提供BackgroundSubtractorMOG2類getBackgroundImage的API介面, * 所以通過FindBackground類定義擷取背景的方法,FindBackground類的初始化工作和 * BackgroundSubtractorMOG2類一致,必須在Frame迴圈之外完成,擷取背景的方法在幀迴圈體內。 */public class GetBGImage extends BackgroundSubtractorMOG2{    //繼承自BackgroundSubtractorMOG2,其構造方法繼承父類構造方法    public  GetBGImage (int history, float varThreshold, boolean bShadowDetection)    {        super( history, varThreshold, bShadowDetection) ;        return;    }    //FindBackground extends BackgroundSubtractorMOG2 extends BackgroundSubtractor extends Algorithm類    //algorithm類定義了long類型的nativeobj    public long getNativeObjAddr() {        return nativeObj;    }    public void FindFeature(Mat mGr, Mat mBG){        FindFeatures(nativeObj, mGr.nativeObj, mBG.nativeObj);        return;    }    public static native void FindFeatures(long nativeObj,long mGr_nativeObj, long mBG_nativeObj);}

 

  2、編寫Java_com_example_Myapplication_GetBGImage.cpp代碼:

#include <jni.h>#include <opencv2/core/core.hpp>#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/features2d/features2d.hpp>#include <vector>#include <android/log.h>#include <sys/time.h>#include <opencv2/video/background_segm.hpp>#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "ProjectName", __VA_ARGS__)using namespace std;using namespace cv;//異常處理,可以不要static void throwJavaException(JNIEnv *env, const std::exception *e, const char *method) {  std::string what = "unknown exception";  jclass je = 0;  if(e) {    std::string exception_type = "std::exception";    if(dynamic_cast<const cv::Exception*>(e)) {      exception_type = "cv::Exception";      je = env->FindClass("org/opencv/core/CvException");    }    what = exception_type + ": " + e->what();  }  if(!je) je = env->FindClass("java/lang/Exception");  env->ThrowNew(je, what.c_str());  LOGE("%s caught %s", method, what.c_str());  (void)method;        // avoid "unused" warning}//方法主體,一定要以extern "C"{開頭extern "C" {JNIEXPORT void JNICALL Java_com_example_Myapplication_GetBGImage_FindFeatures(JNIEnv* , jobject ,                                                                                  jlong self,                                                                                  jlong addrGray,                                                                                  jlong addrBG);//在java native方法中傳入的參數主要有三個,分別對應self、addrGray、addrBG,其中self是自訂的GetBGImage類long類型的nativeobj,它可以作為一個指標指向你定義的GetBGImage類對象。//當對象指標通過jni傳入C++後,你可以通過GetBGImage的父類BackgroundSubtractorMOG2的指標指向這個對象,並在通過指標調用C的介面,從而實現對getBackgroundImage方法的調用。JNIEXPORT void JNICALL Java_com_example_Myapplication _GetBGImage_FindFeatures(JNIEnv* env, jobject ,                                                                                  jlong self,                                                                                  jlong addrGray,                                                                                  jlong addrBG)     {    static const char method_name[] ="FindFeatures->getBackgroundImage()getFrontMaskImage()";    try{        LOGE("%s",method_name);        Mat& mGr  = *(Mat*)addrGray;        Mat& mBG = *(Mat*)addrBG;        cv::BackgroundSubtractorMOG2* me = (cv::BackgroundSubtractorMOG2*) self;        me->operator()(mGr, mBG,0.001);        me->getBackgroundImage(mGr);        return;    }catch(const std::exception &e) {        throwJavaException(env, &e, method_name);    } catch (...) {        throwJavaException(env, 0, method_name);    }    return;     }}
  註:需要調用的C++函數需在native裡聲明,聲明的檔案名稱要與編寫的cpp檔案一致,例如Java_com_example_Myapplication_GetBGImage_FindFeatures對應的FindFeatures。   3、產生.h標頭檔和.so庫檔案            產生.h標頭檔(在as terminal中輸入命令:javah -d &location\app\src\main\jni -classpath &location\app\src\main\java com.example.Myapplication.GetBGImage),如果一切順利則不會報錯,並產生Java_com_example_Myapplication_GetBGImage.h檔案;  編寫Android.mk檔案、application.mk檔案,具體請參照Tutorial2或相關部落格,提示一句:如果需要mk多個cpp檔案(例如1.cpp,2.cpp),請在標記LOCAL_SRC_FILES :=1.cpp    LOCAL_SRC_FILES := 2.cpp,當然還有更通用的寫法,可以自己尋找,這裡不再介紹。  編譯.so檔案,as terminal轉入app\src\main\jni目錄下,輸入ndk-build,如果一切順利則會提示產生了一系列.so檔案,同時你的project的main目錄下會產生libs和obj兩個目錄。這就表示編譯成功,在你的mainActivity裡載入這個.so檔案吧,載入方法:  BaseLoaderCallback中載入System.loadLibrary("xxxx");    //.so檔案名稱一般為libxxxx.so  這一步很關鍵,也很容易出錯,請耐心調試,如果我的方法不適用可以多搜別人的部落格看看。            4、完成以上步驟,就可以放心使用GetBGImage的FindFeature方法了。步驟可以參考java背景建模,首先預定義GetBGImage類對象          
public class Tutorial2Activity extends Activity implements CvCameraViewListener2 {  ……  private Mat                    mRgba;  private Mat                    mIntermediateMat;  private Mat                    mGray;  private GetBGImage             mog2;
  在onCameraViewStarted方法中進行初始化,這裡
public void onCameraViewStarted(int width, int height) {    mRgba = new Mat(height, width, CvType.CV_8UC4);    mIntermediateMat = new Mat(height, width, CvType.CV_8UC1);    mGray = new Mat(height, width, CvType.CV_8UC1);     //GetBGImage類繼承自BackgroundSubtractorMOG2,其構造方法繼承父類構造方法    bg2 = new GetBGImage(30,16,false);

  這裡的參數請參照背景建模的需求進行調試。

  在onCameraFrame方法中調用FindFeature
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {    mGray = inputFrame.gray();    bg2.FindFeature(mGray,mIntermediateMat );

 

          以上。 

OpenCV4Android背景建模(MOG、MOG2)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.