本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃
 
 
  很久以前的笔记了,分享给大家吧。。。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)的更多相关文章

  1. [MOC062066]背景建模资料收集整理

    一.相关博客 背景建模相关资料收集,各个链接都已给出. 资料,不可能非常完整,以后不定期更新. -----------------切割线----------------- 这个哥们总结的非常好啊,看完 ...

  2. OpenCV笔记(6)(harris角点检测、背景建模)

    一.Harris角点 如上图所示,红色框AB都是平面,蓝色框CD都是边缘,而绿色框EF就是角点. 平面:框往X或Y抽移动,变化都很小. 边缘:框沿X或Y轴移动,其中一个变化很小,而另外一个变化比较大. ...

  3. 【背景建模】SOBS

    SOBS(self-Organizing through artificial neural networks)是一种基于自组织神经网络的背景差分算法,主要是借鉴神经网络的特性,一个网络输入节点,对应 ...

  4. 【背景建模】PbModel

    PbModel是基于概率模型的背景差分算法,其基本思想是像素点会因光照变化.运动物体经过产生多种颜色值,但是一段时间内,像素点处于静止状态的时间会比处于运动状态的时间长.因而一段时间内,像素点某个颜色 ...

  5. 【背景建模】VIBE

    ViBe是一种像素级的背景建模.前景检测算法,该算法主要不同之处是背景模型的更新策略,随机选择需要替换的像素的样本,随机选择邻域像素进行更新.在无法确定像素变化的模型时,随机的更新策略,在一定程度上可 ...

  6. 【背景建模】PBAS

    Pixel-Based Adaptive Segmenter(PBAS)检测算法,是基于像素的无参数模型,该算法结合了SACON和VIBE两个算法的优势,并在这两个算法的基础上改进而来,SACON和V ...

  7. OpenCV ——背景建模之CodeBook(2)

    1,CodeBook的来源 先考虑平均背景的建模方法.该方法是针对每一个像素,累积若干帧的像素值,然后计算平均值和方差,以此来建立背景模型,相当于模型的每一个像素含有两个特征值,这两个特征值只是单纯的 ...

  8. OpenCV ——背景建模之CodeBook(1)

    1,CodeBook算法流程介绍 CodeBook算法的基本思想是得到每个像素的时间序列模型.这种模型能很好地处理时间起伏,缺点是需要消耗大量的内存.CodeBook算法为当前图像的每一个像素建立一个 ...

  9. 背景建模或前景检測之PBAS

    申明,本文非笔者原创,原文转载自:http://blog.csdn.net/kcust/article/details/9931575 Pixel-Based Adaptive Segmenter(P ...

随机推荐

  1. SpringMVC第四篇【参数绑定详讲、默认支持参数类型、自定义参数绑定、RequestParam注解】

    参数绑定 我们在Controller使用方法参数接收值,就是把web端的值给接收到Controller中处理,这个过程就叫做参数绑定- 默认支持的参数类型 从上面的用法我们可以发现,我们可以使用req ...

  2. js 第一课

    什么是JavaScript JavaScript是一种脚本语言,运行在网页上.无需安装编译器.只要在网页浏览器上就能运行 一般JavaScript与HTML合作使用. 例如 <html> ...

  3. Redis学习笔记之二 :在Java项目中使用Redis

    成功配置redis之后,便来学习使用redis.首先了解下redis的数据类型. Redis的数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set( ...

  4. angular 学习笔记

    每天进步一点点,学习笔记 笔记来自  angular权威指南 如果想要屏蔽浏览器对表单的默认验证行为,可以在表单元素上添加 novalidate 标记. 而按钮标签则完全忽略 hr e f 属性,并不 ...

  5. 【 js 基础 】关于this

    this 关键字是 Javascript 中很特别的一个关键字,被自动定义在所有函数的作用域中.this提供了一种更优雅的方式隐式"传递"一个对象的引用.今天就来说说 this 的 ...

  6. java程序员该工作还是游戏?

    前阵子我终于下定决心,删掉了硬盘里所有的游戏. 身为一个程序猿,每天都要和各种新技术打交道,闲暇时间,总还得看一下各大论坛,逛逛博客园啥的,给自己充充电.游戏的话,其实我自小就比较喜欢,可以算是一种兴 ...

  7. 网站如何集成百度UEditor编辑器

    在平时的网站维护使用过程中,富文本编辑器是网站必不可少的元素之一.现在市面上各种编辑器功能设计参差不齐,自己做了几个网站都是用蝉知建站系统做的,而蝉知默认内置的编辑器是KindEditor,功能简单, ...

  8. BZOJ-1050-[HAOI2006]旅行comf(并查集)

    Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求 一条路径,使得路径上最 ...

  9. bzoj3713 [PA2014]Iloczyn|暴力(模拟)

    斐波那契数列的定义为:k=0或1时,F[k]=k:k>1时,F[k]=F[k-1]+F[k-2].数列的开头几项为0,1,1,2,3,5,8,13,21,34,55,-你的任务是判断给定的数字能 ...

  10. Gaussian and Truncated Gaussian

    Everybody knows about Gaussian distribution, and Gaussian is very popular in Bayesian world and even ...