当前位置: 编程技术>综合
本页文章导读:
▪我的OpenCV学习笔记(25):c++版本的高斯混合模型的源代码完全注释 之前看到过C版本的,感觉写的很长,没有仔细看,但是C++版本的写的还是很不错的。我仔细看了一下,并对内容进行了仔细的注释,如果有人没有看懂,欢迎留言讨论。
先看一眼头.........
▪linux下部分头文件的作用 除去内核源码下的include目录外,在arch/arm/mach-s3c2410/和arch/arm/plat-s3c24xx/目录下都有include目录的。
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> .........
▪操作系统大型实验进展(1)-----c++ 初始化文件 #include <iostream>
#include <crtdbg.h>
using namespace std;
FILE *fp;
char SP_NAME[]="cq.dat";
int BLOCK_NUM=65536;//64*1024
int BLOCK_SIZE=512;
#define biteNum 33554432//64*1024*512
void init() {
int i,j;
fp = fopen(SP_NAME.........
[1]我的OpenCV学习笔记(25):c++版本的高斯混合模型的源代码完全注释
来源: 互联网 发布时间: 2013-11-10
之前看到过C版本的,感觉写的很长,没有仔细看,但是C++版本的写的还是很不错的。我仔细看了一下,并对内容进行了仔细的注释,如果有人没有看懂,欢迎留言讨论。
先看一眼头文件,在background_segm.hpp中
class CV_EXPORTS_W BackgroundSubtractorMOG : public BackgroundSubtractor { public: //! the default constructor CV_WRAP BackgroundSubtractorMOG(); //! the full constructor that takes the length of the history, the number of gaussian mixtures, the background ratio parameter and the noise strength CV_WRAP BackgroundSubtractorMOG(int history, int nmixtures, double backgroundRatio, double noiseSigma=0); //! the destructor virtual ~BackgroundSubtractorMOG(); //! the update operator virtual void operator()(InputArray image, OutputArray fgmask, double learningRate=0); //! re-initiaization method virtual void initialize(Size frameSize, int frameType); virtual AlgorithmInfo* info() const; protected: Size frameSize; int frameType; Mat bgmodel; int nframes; int history;//利用历史帧数计算学习速率,不是主要参数 int nmixtures;//高斯模型的个数 double varThreshold;//方差门限 double backgroundRatio;//背景门限 double noiseSigma;//噪声方差 };
再看一眼源文件,在bgfg_gaussmix.cpp中:
static const int defaultNMixtures = 5;//默认混合模型个数 static const int defaultHistory = 200;//默认历史帧数 static const double defaultBackgroundRatio = 0.7;//默认背景门限 static const double defaultVarThreshold = 2.5*2.5;//默认方差门限 static const double defaultNoiseSigma = 30*0.5;//默认噪声方差 static const double defaultInitialWeight = 0.05;//默认初始权值 //不带参数的构造函数,使用默认值 BackgroundSubtractorMOG::BackgroundSubtractorMOG() { frameSize = Size(0,0); frameType = 0; nframes = 0; nmixtures = defaultNMixtures; history = defaultHistory; varThreshold = defaultVarThreshold; backgroundRatio = defaultBackgroundRatio; noiseSigma = defaultNoiseSigma; } //带参数的构造函数,使用参数传进来的值 BackgroundSubtractorMOG::BackgroundSubtractorMOG(int _history, int _nmixtures, double _backgroundRatio, double _noiseSigma) { frameSize = Size(0,0); frameType = 0; nframes = 0; nmixtures = min(_nmixtures > 0 ? _nmixtures : defaultNMixtures, 8);//不能超过8个,否则就用默认的 history = _history > 0 ? _history : defaultHistory;//不能小于0,否则就用默认的 varThreshold = defaultVarThreshold;//门限使用默认的 backgroundRatio = min(_backgroundRatio > 0 ? _backgroundRatio : 0.95, 1.);//背景门限必须大于0,小于1,否则使用0.95 noiseSigma = _noiseSigma <= 0 ? defaultNoiseSigma : _noiseSigma;//噪声门限大于0 } BackgroundSubtractorMOG::~BackgroundSubtractorMOG() { } void BackgroundSubtractorMOG::initialize(Size _frameSize, int _frameType) { frameSize = _frameSize; frameType = _frameType; nframes = 0; int nchannels = CV_MAT_CN(frameType); CV_Assert( CV_MAT_DEPTH(frameType) == CV_8U ); // for each gaussian mixture of each pixel bg model we store ... // the mixture sort key (w/sum_of_variances), the mixture weight (w), // the mean (nchannels values) and // the diagonal covariance matrix (another nchannels values) bgmodel.create( 1, frameSize.height*frameSize.width*nmixtures*(2 + 2*nchannels), CV_32F );//初始化一个1行*XX列的矩阵 //XX是这样计算的:图像的行*列*混合模型的个数*(1(优先级) + 1(权值) + 2(均值 + 方差) * 通道数) bgmodel = Scalar::all(0);//清零 } //设为模版,就是考虑到了彩色图像与灰度图像两种情况 template<typename VT> struct MixData { float sortKey; float weight; VT mean; VT var; }; static void process8uC1( const Mat& image, Mat& fgmask, double learningRate, Mat& bgmodel, int nmixtures, double backgroundRatio, double varThreshold, double noiseSigma ) { int x, y, k, k1, rows = image.rows, cols = image.cols; float alpha = (float)learningRate, T = (float)backgroundRatio, vT = (float)varThreshold;//学习速率、背景门限、方差门限 int K = nmixtures;//混合模型个数 MixData<float>* mptr = (MixData<float>*)bgmodel.data; const float w0 = (float)defaultInitialWeight;//初始权值 const float sk0 = (float)(w0/(defaultNoiseSigma*2));//初始优先级 const float var0 = (float)(defaultNoiseSigma*defaultNoiseSigma*4);//初始方差 const float minVar = (float)(noiseSigma*noiseSigma);//最小方差 for( y = 0; y < rows; y++ ) { const uchar* src = image.ptr<uchar>(y); uchar* dst = fgmask.ptr<uchar>(y); if( alpha > 0 )//如果学习速率为0,则退化为背景相减 { for( x = 0; x < cols; x++, mptr += K ) { float wsum = 0; float pix = src[x];//每个像素 int kHit = -1, kForeground = -1;//是否属于模型,是否属于前景 for( k = 0; k < K; k++ )//每个高斯模型 { float w = mptr[k].weight;//当前模型的权值 wsum += w;//权值累加 if( w < FLT_EPSILON ) break; float mu = mptr[k].mean;//当前模型的均值 float var = mptr[k].var;//当前模型的方差 float diff = pix - mu;//当前像素与模型均值之差 float d2 = diff*diff;//平方 if( d2 < vT*var )//是否小于方门限,即是否属于该模型 { wsum -= w;//如果匹配,则把它减去,因为之后会更新它 float dw = alpha*(1.f - w); mptr[k].weight = w + dw;//增加权值 //注意源文章中涉及概率的部分多进行了简化,将概率变为1 mptr[k].mean = mu + alpha*diff;//修正均值 var = max(var + alpha*(d2 - var), minVar);//开始时方差清零0,所以这里使用噪声方差作为默认方差,否则使用上一次方差 mptr[k].var = var;//修正方差 mptr[k].sortKey = w/sqrt(var);//重新计算优先级,貌似这里不对,应该使用更新后的mptr[k].weight而不是w for( k1 = k-1; k1 >= 0; k1-- )//从匹配的第k个模型开始向前比较,如果更新后的单高斯模型优先级超过他前面的那个,则交换顺序 { if( mptr[k1].sortKey >= mptr[k1+1].sortKey )//如果优先级没有发生改变,则停止比较 break; std::swap( mptr[k1], mptr[k1+1] );//交换它们的顺序,始终保证优先级最大的在前面 } kHit = k1+1;//记录属于哪个模型 break; } } if( kHit < 0 ) // no appropriate gaussian mixture found at all, remove the weakest mixture and create a new one //当前像素不属于任何一个模型 { //初始化一个新模型 kHit = k = min(k, K-1);//有两种情况,当最开始的初始化时,k并不是等于K-1的 wsum += w0 - mptr[k].weight;//从权值总和中减去原来的那个模型,并加上默认权值 mptr[k].weight = w0;//初始化权值 mptr[k].mean = pix;//初始化均值 mptr[k].var = var0; //初始化方差 mptr[k].sortKey = sk0;//初始化权值 } else for( ; k < K; k++ ) wsum += mptr[k].weight;//求出剩下的总权值 float wscale = 1.f/wsum;//归一化 wsum = 0; for( k = 0; k < K; k++ ) { wsum += mptr[k].weight *= wscale; mptr[k].sortKey *= wscale;//计算归一化权值 if( wsum > T && kForeground < 0 ) kForeground = k+1;//第几个模型之后就判为前景了 } dst[x] = (uchar)(-(kHit >= kForeground));//判决:(ucahr)(-true) = 255;(uchar)(-(false)) = 0; } } else//如果学习速率小于等于0,则没有背景更新过程,其他过程类似 { for( x = 0; x < cols; x++, mptr += K ) { float pix = src[x]; int kHit = -1, kForeground = -1; for( k = 0; k < K; k++ ) { if( mptr[k].weight < FLT_EPSILON ) break; float mu = mptr[k].mean; float var = mptr[k].var; float diff = pix - mu; float d2 = diff*diff; if( d2 < vT*var ) { kHit = k; break; } } if( kHit >= 0 ) {
[2]linux下部分头文件的作用
来源: 互联网 发布时间: 2013-11-10
除去内核源码下的include目录外,在arch/arm/mach-s3c2410/和arch/arm/plat-s3c24xx/目录下都有include目录的。
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* file_operations、inode_operations、super_operations结构体*/
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t等各种系统typedef的数据类型 */
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/poll.h> /* COPY_TO_USER */
#include <linux/module.h> /*MODULE_LICENSE("GPL");内核认识的特定许可有, "GPL"( 适用 GNU 通用公共许可的任何版本 ), "GPL v2"( 只适用 GPL 版本 2 ), "GPL and additional rights", "Dual BSD/GPL", "Dual MPL/GPL", "Proprietary". 除非你的模块明确标识是在内核认识的一个自由许可下, 否则就假定它是私有的, 内核在模块加载时被"弄污浊"了. 象我们在第 1 章"许可条款"中提到的, 内核开发者不会热心帮助在加载了私有模块后遇到问题的用户. MODULE_AUTHOR ( 声明谁编写了模块 ), MODULE_DESCRIPION( 一个人可读的关于模块做什么的声明 ), MODULE_VERSION ( 一个代码修订版本号; 看 <linux/module.h> 的注释以便知道创建版本字串使用的惯例), MODULE_ALIAS ( 模块为人所知的另一个名子 ), MODULE_DEVICE_TABLE ( 来告知用户空间, 模块支持那些设备 ). */
#include <linux/init.h> /* #define module_init(x) __initcall(x); driver initialization entry point #define module_exit(x) __exitcall(x); driver exit entry point */
#include <linux/miscdevice.h> /* extern int misc_register(struct miscdevice * misc); 注册miscdevice结构体成员变量设备 extern int misc_deregister(struct miscdevice *misc); 注销miscdevice结构体成员变量设备 */
#include <linux/cdev.h> /* void cdev_init(struct cdev *, const struct file_operations *); struct cdev *cdev_alloc(void); void cdev_put(struct cdev *p); int cdev_add(struct cdev *, dev_t, unsigned); void cdev_del(struct cdev *); void cd_forget(struct inode *); */
#include <mach/hardware.h> /* 和GPIO口操作相关的函数定义的头文件 对应的源文件在/linux-2.6.32.2/arch/arm/plat-s3c24xx/gpio.c void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function); unsigned int s3c2410_gpio_getcfg(unsigned int pin); void s3c2410_gpio_pullup(unsigned int pin, unsigned int to); int s3c2410_gpio_getpull(unsigned int pin); void s3c2410_gpio_setpin(unsigned int pin, unsigned int to); unsigned int s3c2410_gpio_getpin(unsigned int pin); unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change); int s3c2410_gpio_getirq(unsigned int pin); int s3c2410_gpio_irq2pin(unsigned int irq);*/ #include <mach/regs-gpio.h> /* 和GPIO口相关的一些宏定义(在arch/arm/mach-s3c2410/mach) */
#include <linux/platform_device.h> /* */
#include <linux/interrupt.h> /* typedef irqreturn_t (*irq_handler_t)(int, void *); extern void free_irq(unsigned int, void *);extern void disable_irq(unsigned int irq); extern void enable_irq(unsigned int irq);等和中断相关函数的声明 */
#include <linux/wait.h> /* wake_up_interruptible 唤醒 q 指定的注册在等待队列上的进程。该函数不能直接的立即唤醒进程,而是由调度程序转换上下文,调整为可运行状态。 static DECLARE_WAIT_QUEUE_HEAD(button_waitq);声明等待队列为全局变量 wait_event_interruptible该函数修改task的状态为TASK_INTERRUPTIBLE,意味着改进程将不会继续运行直到被唤醒,然后被添加到等待队列wq中*/
#include <linux/poll.h> /* poll_wait */
#include <asm/uaccess.h> /* copy_to_user和copy_from_user */ #include <asm/io.h> /* __raw_readl __raw_writel*/
#include <linux/clk.h> /* struct clk *clk_get(struct device *dev, const char *id); unsigned long clk_get_rate(struct clk *clk); */
#include <plat/clock.h> /* struct clk;结构体的定义 (在arch/arm/plat-s3c/plat/include/clock.arch中,对应的源文件在/arm/plat-s3c/clock.c)*/
#include <linux/device.h> //包含了device、class 、device_driver等结构的定义
#include <mach/regs-mem.h> /* 和bank相关的寄存器的宏定义 */
#include <asm/div64.h> /* Linux内核中64位除法函数do_div */
#include <linux/fb.h> /* struct fb_info 结构体的定义 */
#include <mach/fb.h> /* struct s3c2410fb_display(在arch/arm/mach-s3c2410/include/mach/fb.h) */
作者:taozi343805436 发表于2013-1-8 15:25:31 原文链接
阅读:0 评论:0 查看评论
[3]操作系统大型实验进展(1)-----c++ 初始化文件
来源: 互联网 发布时间: 2013-11-10
#include <iostream> #include <crtdbg.h> using namespace std; FILE *fp; char SP_NAME[]="cq.dat"; int BLOCK_NUM=65536;//64*1024 int BLOCK_SIZE=512; #define biteNum 33554432//64*1024*512 void init() { int i,j; fp = fopen(SP_NAME,"w"); //文件写入方法一 /*for(i=0;i<BLOCK_NUM;i++) { for(j=0;j<BLOCK_SIZE;j++) { fprintf(fp,"%c",'\0'); } } */ //文件写入方法二 char *memory=(char*)malloc(biteNum);//http://baike.baidu.com/view/736228.htm memset(memory,0,biteNum); fwrite(memory,1,biteNum,fp);//http://baike.baidu.com/view/656700.htm fclose(fp); free(memory); } int main() { init(); return 0; }
作者:chenqiai0 发表于2013-1-8 15:24:25 原文链接
阅读:12 评论:0 查看评论
最新技术文章: