索引地址:系列教程索引地址
产生随机数是编程中经常用到的操作,特别在进行初始化的时候需要赋一些随机值。C和C++
中产生随机数的方法如rand()、srand()等在OpenCV中仍可以用。此外,OpenCV还特地编写了C++
的随机数类RNG,还有一些相关的函数,使用起来更加方便。下面一一介绍。
说明
- 计算机产生的随机数都是伪随机数,是根据种子seed和特定算法计算出来的。所以,只要种子一定,算法一定,产生的随机数是相同的
- 要想产生完全重复的随机数,可以用系统时间做种子。OpenCV中用GetTickCount(),C 中用time()
RNG
RNG类是opencv里C++的随机数产生器。它可产生一个64位的int随机数。目前可按均匀分布和高斯分布产生随机数。随机数的产生采用的是Multiply-With-Carry算法和Ziggurat算法。
函数原型:
| RNG(int seed); RNG::uniform(); RNG::gaussian(); RNG::uniform(a, b); RNG::gaussian(σ);
|
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std;
int main() { RNG rng;
int rand1 = rng; cout<<"rand1="<<rand1<<endl;
double rand2 = rng.uniform(0, 1); cout<<"rand2="<<rand2<<endl;
double rand3 = rng.uniform((double)0, (double)1); cout<<"rand3="<<rand3<<endl;
double rand4 = rng.uniform(0.f, 1.f); cout<<"rand4="<<rand4<<endl;
double rand5 = rng.uniform(0., 1.); cout<<"rand5="<<rand5<<endl;
double rand6 = rng.gaussian(2); cout<<"rand6="<<rand6<<endl;
return 0; }
|
输出为:
| rand1=130063606 rand2=0 rand3=0.901059 rand4=0.937133 rand5=0.74879 rand6=0.610327
|
返回下一个随机数
上面代码一次只能返回一个随机数,实际上系统已经生成一个随机数组。如果我们要连续获得随机数,没有必要重新定义一个RNG类,只需要取出随机数组的下一个随机数即可。
| RNG::next(); RNG::double(); RNG::operator()();
|
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std;
int main() { int a[11]={0}; RNG rng; a[0] = rng.next();
a[1] = rng.operator uchar(); a[2] = rng.operator schar(); a[3] = rng.operator ushort(); a[4] = rng.operator short int(); a[5] = rng.operator int(); a[6] = rng.operator unsigned int(); a[7] = rng.operator float(); a[8] = rng.operator double(); a[9] = rng.operator()(); a[10] = rng.operator()(100);
for(int i=0;i<11;i++){ cout<<"a["<<i<<"]="<<a[i]<<endl; }
return 0; }
|
测试结果:
| a[0]=130063606 a[1]=165 a[2]=-25 a[3]=35421 a[4]=-3479 a[5]=-1078939986 a[6]=1172977286 a[7]=0 a[8]=0 a[9]=-92568545 a[10]=38
|
用随机数填充矩阵
| void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange=false );
|
参数说明:
- InputOutputArray 输入输出矩阵,最多支持4通道,超过4通道先用reshape()改变结构
- int distType UNIFORM 或 NORMAL,表示均匀分布和高斯分布
- InputArray a disType是UNIFORM,a表示为下界(闭区间);disType是NORMAL,a均值
- InputArray b disType是UNIFORM,b表示为上界(开区间);disType是NORMAL,b标准差
- bool saturateRange=false 只针对均匀分布有效。当为真的时候,会先把产生随机数的范围变换到数据类型的范围,再产生随机数;如果为假,会先产生随机数,再进行截断到数据类型的有效区间。
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std;
int main() { RNG rng; Mat_<int> fillM(3, 3); rng.fill(fillM, RNG::UNIFORM, 1, 1000); cout << "filM = " << fillM << endl << endl;
Mat fillM1(3, 3, CV_8U); rng.fill(fillM1, RNG::UNIFORM, 1, 1000, true); cout << "filM1 = " << fillM1 << endl << endl;
Mat fillM2(3, 3, CV_8U); rng.fill(fillM2, RNG::UNIFORM, 1, 1000, false); cout << "filM2 = " << fillM2 << endl << endl;
Mat_<double> fillN(3, 3); rng.fill(fillN, RNG::NORMAL, 1, 3); cout << "filN = " << fillN << endl << endl;
return 0; }
|
测试结果:
| filM = [800, 699, 734; 255, 482, 557; 438, 804, 800]
filM1 = [240, 27, 249; 208, 219, 46; 184, 159, 102]
filM2 = [205, 1, 206; 255, 255, 255; 255, 255, 255]
filN = [-3.098058104515076, 0.8102578073740005, 5.054980039596558; 3.397326588630676, 0.2112799882888794, -0.5630163550376892; 6.498937964439392, 2.099618792533875, 4.876072406768799]
|
问题来了,如果进行多次运行,每次运行的结果是一样的,
可以采取另一种方式,用系统时间作为种子初始化rng
| RNG rng((unsigned)time(NULL));
|
开始生成随机数啦
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <iostream> #include <time.h> #include <opencv2/opencv.hpp> using namespace cv; using namespace std;
int main() { RNG rng((unsigned)time(NULL));
double x=rng.uniform((double)0,(double)255); cout<<"x="<<x<<endl; float y=rng.uniform(0.f,255.f); cout<<"y="<<y<<endl; int z=rng.uniform((int)0, (int)255 ); cout<<"z="<<z<<endl;
return 0; }
|
每次运行生成的随机数都不一样哦~
| x=54.1418 y=62.9061 z=120
x=38.6976 y=251.299 z=183
x=23.2534 y=184.693 z=247
|