OpenCV Advent Calendar 2015 26日目
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
OpenCV Advent Calendar 2015 26日目
*はじめに [#x82ae35e]
-[[OpenCV Advent Calendar 2015>http://qiita.com/advent-ca...
-OpenCVに入ってるRNG(Random Number Generator)クラスで乱数...
*乱数をOpenCV内で使う場面 [#t7026595]
-OpenCV内では、関数が想定通りの挙動を示すかどうかテストを...
-その際、大量にデータを生成するのに使われるのがRNGクラス...
*RNG の実装を見てみよう [#t5a91997]
-RNGクラスはcore.hpp と rand.cpp内に記述があります
Random number generator. It encapsulates the state (curr...
integer) and has methods to return scalar random values ...
arrays with random values. Currently it supports uniform...
(normal) distributions. The generator uses Multiply-With...
algorithm, introduced by G. Marsaglia (
<http://en.wikipedia.org/wiki/Multiply-with-carry> ).
Gaussian-distribution random numbers are generated using...
algorithm ( <http://en.wikipedia.org/wiki/Ziggurat_algor...
introduced by G. Marsaglia and W. W. Tsang.
-というふうにコメント内に説明があります
-日本語でおkということなので、ざっくり和訳してみます。
乱数生成器。内部に状態を保持し(状態は64bit整数)、
乱数スカラ値を返し、もしくは行列を乱数で埋める。
現在サポートされてるのは一様分布とガウシアン(正規)分布。
生成器は内部でMultiply-With-Carryアルゴリズムを使う。
G. Marsaglia ( <http://en.wikipedia.org/wiki/Multiply-wi...
ガウシアン分布の乱数はZigguratのアルゴリズム
( <http://en.wikipedia.org/wiki/Ziggurat_algorithm> ) を...
-ざっくりまとめると、一様分布と正規分布の乱数を生成できる...
-ちなみに、一様分布の生成アルゴリズム[[Multiply with carr...
-それにしてもジグラットって。バーチャロンを彷彿させる。
-早速、使ってみましょう。
*一様分布 [#fd14275b]
-一様分布は、seedでインスタンスを生成した後、a.next()で新...
#geshi(C++){{
#include <iostream>
#include <iomanip>
#include <opencv2/core/core.hpp>
const uint64 initState = 0x1234354435;
int main()
{
using namespace cv;
using namespace std;
RNG a(initState);
for(int i = 0;i < 10;i++)
{
unsigned int randomNumber = a.next();
cout << "0x" << std::hex << std::setw(8) << std::setfil...
}
return 0;
}
}}
-出力結果
0xc4802924
0x6f670ec9
0x4ec21e44
0xe40ce671
0x5fcd40f9
0x3090cb5e
0x5d55db31
0x7145ce59
0xc5efc30e
0x7215b472
-と、こんな感じに32bitの乱数が生成されます。
-charやshortが必要だったらマスキングしましょう。
-この一様分布のスゴいところは、実装が掛け算とマスキングだ...
-なので、OpenCVを使いながらも、libファイルとリンクしない...
#geshi(C++){{
//operations.hpp
inline RNG::RNG(uint64 _state) { state = _state ? _state ...
//中略
inline unsigned RNG::next()
{
state = (uint64)(unsigned)state* /*CV_RNG_COEFF*/ 416...
return (unsigned)state;
}
}}
-なんと以上。
-内部の状態変数と掛け算と足し算を行うことで新しい数を生成...
-実装が簡単なだけあって、速度もそこそこ出ます。
-試しに1000000回生成してみました。
#geshi(c++){{
int64 start = cv::getTickCount();
for(unsigned int i = 0;i < iteration;i++)
{
a.next();
}
int64 finish = getTickCount();
std::cout << "0x" << std::hex << a.next() << std::endl;
std::cout << (finish - start) * second2ms / getTickFrequ...
std::cout << ((finish - start) * second2ms / getTickFreq...
}}
-実行結果
0xd497e65c
1.5647ms for generating 1000000 random #
1.5647e-006ms / 1 random #
-用途によりますが、これぐらい速いんだったら様々な場面で活...
-参考までに、ヒストグラムを作ってみました。
#ref(rng-uniform.png)
*正規分布 [#a09ee15a]
-正規分布は、gaussianメソッドを呼ぶことでdouble型の値が返...
-このgaussianメソッドにはsigmaを渡すことができ、分散がsig...
-実際に使ってみましょう。
#geshi(c++){{
const unsigned int cIteration = 8000000;
const double second2ms = 1000.0f;
const double kSigma = 3.0f;
void checkEachBitVarianceGaussian(uint64 init, unsigned i...
{
using namespace cv;
RNG a(init);
double foo = a.gaussian(kSigma);
int64 start = cv::getTickCount();
for(unsigned int i = 0;i < iteration;i++)
{
a.gaussian(kSigma);
}
int64 finish = getTickCount();
foo = a.gaussian(kSigma);
std::cout << (finish - start) * second2ms / getTickFrequ...
std::cout << ((finish - start) * second2ms / getTickFreq...
std::cout << foo << std::endl;
}
}}
-実行結果
24.3736ms for generating 1000000 gaussian distributed ra...
2.43736e-005ms / 1 random #
-0.965316
-一様分布の場合は1回あたりの生成が平均1.5647e-006ms でし...
-ついでに正規分布の様子をヒストグラムで見てみましょう。
#geshi(c++){{
using namespace cv;
RNG a(init);
unsigned int count[60]; //ヒストグラムのカウント
memset(count, 0, sizeof(unsigned int)*60);
// ヒストグラム作成
for(unsigned int i = 0;i < iteration;i++)
{
double foo = a.gaussian(kSigma);
int index = (int)(foo * 3 + 30);
index = index < 0 ? 0 : index;
index = index >= 60 ? 59 : index;
count[index]++;
}
// ヒストグラム出力
for(int i = 0;i < 60;i++)
{
std::cout << std::setw(2) << i << ' ' << ((double)(i-30...
}
}}
-でグラフにしてみました。
#ref(rng-gaussian.png)
-なかなか綺麗な分布ですね。
*OpenCV内での本来の使い方 [#hd200c0a]
-前述の通り、本来は大量のテストデータを生成するために使わ...
#geshi(c++){{
Mat randomMat(RNG& rng, Size size, int type, double minVa...
{
Size size0 = size;
if( useRoi )
{
size0.width += std::max(rng.uniform(0, 10) - 5, 0);
size0.height += std::max(rng.uniform(0, 10) - 5, ...
}
Mat m(size0, type);
rng.fill(m, RNG::UNIFORM, minVal, maxVal); // ここで...
if( size0 == size )
return m;
return m(Rect((size0.width-size.width)/2, (size0.heig...
}
}}
-fill関数を使うと、配列の中身を乱数で埋めることができます。
-こちらの解説を始めるとOpenCVのテストの仕組みをまるっと解...
*終わりに [#r79dfced]
-RNGのuniformが軽い割に、そこそこ一様分布していたのには驚...
-ゆくゆくは、OpenCVのテスト、Google Test に関して記事を書...
-企画、そして実に9日分の記事を書いてくださった fukushima1...
*補足情報 [#o7e0f117]
-Core i7 3720QM 2.60GHz
-Windows 7 Ultimate 64bit
-OpenCV 3.1 <- new!
-Visual Studio 2012 update 4
[[OpenCV Advent Calendar 2015 16日目]]
[[:OpenCV]]
[[:OpenCV 3.1]]
終了行:
OpenCV Advent Calendar 2015 26日目
*はじめに [#x82ae35e]
-[[OpenCV Advent Calendar 2015>http://qiita.com/advent-ca...
-OpenCVに入ってるRNG(Random Number Generator)クラスで乱数...
*乱数をOpenCV内で使う場面 [#t7026595]
-OpenCV内では、関数が想定通りの挙動を示すかどうかテストを...
-その際、大量にデータを生成するのに使われるのがRNGクラス...
*RNG の実装を見てみよう [#t5a91997]
-RNGクラスはcore.hpp と rand.cpp内に記述があります
Random number generator. It encapsulates the state (curr...
integer) and has methods to return scalar random values ...
arrays with random values. Currently it supports uniform...
(normal) distributions. The generator uses Multiply-With...
algorithm, introduced by G. Marsaglia (
<http://en.wikipedia.org/wiki/Multiply-with-carry> ).
Gaussian-distribution random numbers are generated using...
algorithm ( <http://en.wikipedia.org/wiki/Ziggurat_algor...
introduced by G. Marsaglia and W. W. Tsang.
-というふうにコメント内に説明があります
-日本語でおkということなので、ざっくり和訳してみます。
乱数生成器。内部に状態を保持し(状態は64bit整数)、
乱数スカラ値を返し、もしくは行列を乱数で埋める。
現在サポートされてるのは一様分布とガウシアン(正規)分布。
生成器は内部でMultiply-With-Carryアルゴリズムを使う。
G. Marsaglia ( <http://en.wikipedia.org/wiki/Multiply-wi...
ガウシアン分布の乱数はZigguratのアルゴリズム
( <http://en.wikipedia.org/wiki/Ziggurat_algorithm> ) を...
-ざっくりまとめると、一様分布と正規分布の乱数を生成できる...
-ちなみに、一様分布の生成アルゴリズム[[Multiply with carr...
-それにしてもジグラットって。バーチャロンを彷彿させる。
-早速、使ってみましょう。
*一様分布 [#fd14275b]
-一様分布は、seedでインスタンスを生成した後、a.next()で新...
#geshi(C++){{
#include <iostream>
#include <iomanip>
#include <opencv2/core/core.hpp>
const uint64 initState = 0x1234354435;
int main()
{
using namespace cv;
using namespace std;
RNG a(initState);
for(int i = 0;i < 10;i++)
{
unsigned int randomNumber = a.next();
cout << "0x" << std::hex << std::setw(8) << std::setfil...
}
return 0;
}
}}
-出力結果
0xc4802924
0x6f670ec9
0x4ec21e44
0xe40ce671
0x5fcd40f9
0x3090cb5e
0x5d55db31
0x7145ce59
0xc5efc30e
0x7215b472
-と、こんな感じに32bitの乱数が生成されます。
-charやshortが必要だったらマスキングしましょう。
-この一様分布のスゴいところは、実装が掛け算とマスキングだ...
-なので、OpenCVを使いながらも、libファイルとリンクしない...
#geshi(C++){{
//operations.hpp
inline RNG::RNG(uint64 _state) { state = _state ? _state ...
//中略
inline unsigned RNG::next()
{
state = (uint64)(unsigned)state* /*CV_RNG_COEFF*/ 416...
return (unsigned)state;
}
}}
-なんと以上。
-内部の状態変数と掛け算と足し算を行うことで新しい数を生成...
-実装が簡単なだけあって、速度もそこそこ出ます。
-試しに1000000回生成してみました。
#geshi(c++){{
int64 start = cv::getTickCount();
for(unsigned int i = 0;i < iteration;i++)
{
a.next();
}
int64 finish = getTickCount();
std::cout << "0x" << std::hex << a.next() << std::endl;
std::cout << (finish - start) * second2ms / getTickFrequ...
std::cout << ((finish - start) * second2ms / getTickFreq...
}}
-実行結果
0xd497e65c
1.5647ms for generating 1000000 random #
1.5647e-006ms / 1 random #
-用途によりますが、これぐらい速いんだったら様々な場面で活...
-参考までに、ヒストグラムを作ってみました。
#ref(rng-uniform.png)
*正規分布 [#a09ee15a]
-正規分布は、gaussianメソッドを呼ぶことでdouble型の値が返...
-このgaussianメソッドにはsigmaを渡すことができ、分散がsig...
-実際に使ってみましょう。
#geshi(c++){{
const unsigned int cIteration = 8000000;
const double second2ms = 1000.0f;
const double kSigma = 3.0f;
void checkEachBitVarianceGaussian(uint64 init, unsigned i...
{
using namespace cv;
RNG a(init);
double foo = a.gaussian(kSigma);
int64 start = cv::getTickCount();
for(unsigned int i = 0;i < iteration;i++)
{
a.gaussian(kSigma);
}
int64 finish = getTickCount();
foo = a.gaussian(kSigma);
std::cout << (finish - start) * second2ms / getTickFrequ...
std::cout << ((finish - start) * second2ms / getTickFreq...
std::cout << foo << std::endl;
}
}}
-実行結果
24.3736ms for generating 1000000 gaussian distributed ra...
2.43736e-005ms / 1 random #
-0.965316
-一様分布の場合は1回あたりの生成が平均1.5647e-006ms でし...
-ついでに正規分布の様子をヒストグラムで見てみましょう。
#geshi(c++){{
using namespace cv;
RNG a(init);
unsigned int count[60]; //ヒストグラムのカウント
memset(count, 0, sizeof(unsigned int)*60);
// ヒストグラム作成
for(unsigned int i = 0;i < iteration;i++)
{
double foo = a.gaussian(kSigma);
int index = (int)(foo * 3 + 30);
index = index < 0 ? 0 : index;
index = index >= 60 ? 59 : index;
count[index]++;
}
// ヒストグラム出力
for(int i = 0;i < 60;i++)
{
std::cout << std::setw(2) << i << ' ' << ((double)(i-30...
}
}}
-でグラフにしてみました。
#ref(rng-gaussian.png)
-なかなか綺麗な分布ですね。
*OpenCV内での本来の使い方 [#hd200c0a]
-前述の通り、本来は大量のテストデータを生成するために使わ...
#geshi(c++){{
Mat randomMat(RNG& rng, Size size, int type, double minVa...
{
Size size0 = size;
if( useRoi )
{
size0.width += std::max(rng.uniform(0, 10) - 5, 0);
size0.height += std::max(rng.uniform(0, 10) - 5, ...
}
Mat m(size0, type);
rng.fill(m, RNG::UNIFORM, minVal, maxVal); // ここで...
if( size0 == size )
return m;
return m(Rect((size0.width-size.width)/2, (size0.heig...
}
}}
-fill関数を使うと、配列の中身を乱数で埋めることができます。
-こちらの解説を始めるとOpenCVのテストの仕組みをまるっと解...
*終わりに [#r79dfced]
-RNGのuniformが軽い割に、そこそこ一様分布していたのには驚...
-ゆくゆくは、OpenCVのテスト、Google Test に関して記事を書...
-企画、そして実に9日分の記事を書いてくださった fukushima1...
*補足情報 [#o7e0f117]
-Core i7 3720QM 2.60GHz
-Windows 7 Ultimate 64bit
-OpenCV 3.1 <- new!
-Visual Studio 2012 update 4
[[OpenCV Advent Calendar 2015 16日目]]
[[:OpenCV]]
[[:OpenCV 3.1]]
ページ名: