OpenCV随机数的生成
一、概念
1.一般计算机的随机数都是伪随机数,以一个真随机数(种子)作为初始条件,然后用一定的算法迭代产生随机数序列。
2.随机数的“种子”就是产生随机数的第一次使用值,机制是通过一个比较复杂函数,将这个种子的值映射到随机数空间的某一个点上,并且产生的随机数均匀地(或者符合正态分布等)散步在空间中,以后产生的随机数都与前一个随机数有关。
3.RNG : random number generation 随机数生成
(版权声明):参考网络
二、opencv中的函数
1.CvRNG cvRNG(int64 seed);
使用64位长整形种子,初始化随机数生成器状态。
cvGetTickCount();
返回64位长整形的时间数据,在opencv中是为CvRNG设置的专用种子。
2.unsigned cvRandInt(CvRNG* rng);
返回均匀分布的随机32位无符号整型值,并更新RNG的状态; 使用模操作可以获得确定边界的整形数值。
3.double cvRandReal(CvRNG* rng);
返回均匀分布的随即浮点数,范围在0-1(不含1),并更新RNG的状态。
4. voidcvRandArr( CvRNG* rng, CvArr* arr, int dist_type, CvScalar param1,CvScalar param2 );
用随机数填充数组,并更新RNG的状态
arr 输出数组
dist_type 分布类型: CV_RAND_UNI- 均匀分布 ; CV_RAND_NORMAL- 正态分布 或者 高斯分布
param1 分布的第一个参数。如果是均匀分布它是随机数范围的闭下边界。如果是正态分布它是随机数的平均值。
param2 分布的第二个参数。如果是均匀分布它是随机数范围的开上边界。如果是正态分布它是随机数的标准差。
先看一个例子
#include"cv.h"
#include"highgui.h"
#include<stdio.h>
intmain()
{
CvRNGrng=cvRNG(0);
inti=0;
for(i=0;i<5;i++)
printf("%d,",cvRandInt(&rng));
printf("\n");
for(i=0;i<5;i++)
printf("%f,",cvRandReal(&rng));
printf("\n");
}
cvGetTickCount()
返回64位长整数的时间数据,在OpenCV是为CvRNG设置的专用种子。
cvGetTickFrequency()
返回系统时钟频率
cvRNG()
跟一般的C语言srand()使用方法一样,要先给它一个种子,但srand()用到的是unsignedint的32位种子范围,而cvRNG()用的是64位长整数种子。初始化CvRNG资料结构,假如seed给0,它将会自动转成-1。
cvRNG(64位种子)
cvRandInt()
返回均匀分布32位的随机数,均匀分布为统计学上的专有名词,表示长时间下所有数字出现的概率都是一样的,而cvRandint()在opencv里使用的公式
temp= (uint64)(unsigned)temp*1554115554 + (temp >> 32);
这个公式的名称叫Multiply-with-carry(MWC)generator,有兴趣的话可以在网络上找“随机数产生器”,Multiply-with-carry是将64位的种子去产生32位的随机数。
unsignedcvRandInt(CvRNG资料结构)
cvRandReal()
返回均匀分布,0~1之间的随机小数,cvRandReal()的公式则是用
cvRandInt(rng)*2.3283064365386962890625e-10
的方法,其实就是cvRandInt(rng)*2^(-32),也就是将cvRandInt()随机出来的结果(32位除以2的三十二次方,因此,出现的结果将会是0~1之间的小数,也就是随机0~1之间。
三、产生固定分布的随机数
voidcvRand( CvRandState* state, CvArr* arr );
使用随机变量填充arr,内部调用的cvRandArr,cvRandArr的参数是由state提供的,
其中CvRandState是产生随机向量的结构数组,由cvRandInit对CvRandState的初始化,例如:
cvRandInit(&rng_state,0, 1, 0xffffffff, CV_RAND_UNI)
初始化的方式:
cvRandInit(CvRandState资料结构,随机上界,随机下界,均匀分布的参数,指定分布类型(CV_RAND_UNI))
cvRandInit(CvRandState资料结构,平均数,标准差,正态分布参数,正态分布类型(CV_RAND_NORMAL))
如:
CvRandStaterng;
cvRandInit(&rng, 0, 1, -1, CV_RAND_UNI );
同时cvRandSetRange可以在不重新初始化rng状态(CV_RAND_UNI/CV_RAND_NORMAL)的情况下改变已经初始化的rng范围及相关参数。
例如:
cvRandSetRange(&rng, 0, 0.1, 0 );
rng.disttype= CV_RAND_NORMAL;//上边设置rng为CV_RAND_UNI状态,现在改为CV_RAND_NORMAL
另外,可以修改CvRandState数据结构的参数内容,均匀分布的话可以每个信道的上下界常态分布可以修改每个通道的平均数,标准偏差.
cvRandSetRange(CvRandState数据结构,均匀分布上界,均匀分布下界,目标信道数据)
cvRandSetRange(CvRandState数据结构,常态分布平均数,常态分布标准偏差,目标信道数据)
若通道为-1,则改变所有通道。
cvRandNext可以生成符合CvRandState条件的随机数。
unsignedcvRandNext( CvRandState* state );
state
RNGstate initialized by RandInit and, optionally, customized byRandSetRange (though, the latter function does not affect onthe discussed function outcome).
Thefunction cvRandNextreturns uniformly-distributed (regardless of the RNG distributiontype settings) "plain" integer random number and updatesRNG state. It is similar to rand() function from C runtime library,but it always generates 32-bit number whereas rand() returns a numberin between 0 and RAND_MAX which is 2**16 or 2**32, dependingon the platform.