本文为作者原创,转载请注明出处(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. 【SQL】- 基础知识梳理(三) - SQL连接查询

    一.引言 有时为了得到一张报表的完整数据,需要从两个或更多的表中获取结果,这时就用到了"连接查询". 二.连接查询 连接查询的定义: 数据库中的表通过键将彼此联系起来,从而获取这些 ...

  2. 轻松把你的项目升级到PWA

    什么是PWA PWA(Progressive Web Apps,渐进式网页应用)是Google在2015年推出的项目,致力于通过web app获得类似native app体验的网站. 优点 1.无需客 ...

  3. 在github上实现页面托管预览功能

    1.建立个人github pages 仓库 创建新仓库,命名规则为----"你的github账号.github.io", 如图所示: 我的账号是zxpsuper,所以我的个人域名仓 ...

  4. Spring 3.x 读书笔记

    第一:如果使用BeanFactory作为Spring Bean的工厂类,则所有的bean都是在第一次使用该Bean的时候实例化 第二:如果使用ApplicationContext作为Spring Be ...

  5. 使用http -server 搭建本地简易文件服务器

    安装 npm install http-server -g 使用 1. cd project . 2. hs [pwd] -o, 默认是当前路径 ./ 3. 其他选项 -p Port to use ( ...

  6. 机器学习之numpy库中常用的函数介绍(一)

    1. mat() mat()与array的区别: mat是矩阵,数据必须是2维的,是array的子集,包含array的所有特性,所做的运算都是针对矩阵来进行的. array是数组,数据可以是多维的,所 ...

  7. HSF服务的开发与使用

    1.HSF服务的开发 1) 基于Maven创建一个web工程HSFService,如下图,其他的可以自定义. 2)创建好好在src/main目录下创建一个java目录,并将其设置为sources fo ...

  8. windown快速安装xgboost

    记录xgboost的快速安装方式,该方式适合pyhton3.5/3.6版本. 系统: win10 64bit python版本:3.6 1. 下载xgboost编译好的whl包 下载路径为:http: ...

  9. JS使用默认图片代替页面上无法显示的图片

    1.js方法: function replaceErrorImg(obj) { obj.src="images/common/error.bmp"; } 2.jquery绑定 $( ...

  10. 系统出现异常: too many values to unpack (expected 2)

    先感谢[ValueError: too many values to unpack](http://leonzhan.iteye.com/blog/1720315)系统出现异常:打开太多值(预期2)这 ...