Rubyで多項分布からのサンプリング

多項分布を扱うことがあったので、Rubyでサクッと多項分布からのサンプリングを書いてみた。ただし、何も見ずにカンで書いたので合ってるかどうかはまったく保証しません。

#!/usr/bin/ruby
# 多項分布からのサンプリングを行う関数
# probは、各項の確率(総和は1とする)
def samplingFromMultinomialDistribution(prob)
# 累積確率にする
prev=0.0
accprob=prob.map{|x| prev=prev+x }
# 一様乱数生成
r=rand()
# 要素を選択する
return accprob.index{|v| v > r}
end
# 適当な多項分布
p prob=[0.6,0.2,0.1,0.05,0.04,0.01]
# サンプリングして
index=samplingFromMultinomialDistribution(prob)
# その項を出力する
p index

何回か実行してみたけど、それっぽい結果が出ているのでよしとするか…。今回は厳密さとか全くいらないので。
厳密さが要求されるシーンで多項分布を扱っている方々はどんなふうにサンプリングしているのだろう?

gccでは通らないけどVisualStudio2008では通るコード

先生がはまってたので簡単に書いてみた.これなんでダメになるのかな?ちなみにNGな方のエラーメッセージはこちら.

test.cpp: In function ‘int main()’:
test.cpp:19: error: no match for ‘operator=’ in ‘t1 = Test()’
test.cpp:9: note: candidates are: Test& Test::operator=(Test&)

コンストラクタを直接呼んでそれをoperator=に突っ込むときはconstが必要らしい?まぁ常にconst付けてれば問題ないんですが.

OKなコード

#include <iostream>
class Test{
	public:
		Test(){}
		Test(const Test& other){}
		~Test(){}
		const Test& operator=(const Test& other){
			return *this;
		}
};
int main(){
	Test t1;
	Test t2(t1);
	t1=Test();
	return 0;
}

NGなコード

#include <iostream>
class Test{
	public:
		Test(){}
		Test(Test& other){}
		~Test(){}
		Test& operator=(Test& other){
			return *this;
		}
};
int main(){
	Test t1;
	Test t2(t1);
	t1=Test();
	return 0;
}

Matlabを使った画像処理(物体領域抽出編)

最も簡単な背景差分法による物体領域抽出

今まで画像処理はOpenCVでやっていたが,機械学習とかにはMatlabの方がいろいろよさそうなのでMatlabの勉強を兼ねていろいろプログラムを書いていくシリーズ第1弾.
背景差分による物体領域抽出は,物体を含む画像と物体を含まない画像を比較して,その差がしきい値より大きい場所を物体領域として抽出する.

Matlabを使った方法

画像の読み込み

画像の読み込みにはimread関数を使う.img_f=imread(‘input.jpg’);により,物体領域を含む画像を読み込む.また,img_b=imread(‘back.jpg’);により,物体領域を含まない画像を読み込む.

画像の差を求める

単純に引き算( diff = img_f – img_b; )をすることで,画像の差を求めることができる.

しきい値を決める

用いる画像がカラー画像の場合,まずグレースケール化する必要がある.diff_gray=rgb2gray(diff); により,グレースケールの画像を得る.
次に,しきい値を決める.適当な値を自分で決めてもよいが,ここでは大津のしきい値判定法を使って決定する.大津のしきい値判定法はクラス内分散最小化を用いるもので,しきい値は thresh = graythresh( diff_gray );によって求めることができる.

しきい値よりも差が大きい部分を求める

次に,しきい値よりも大きい部分を物体領域(白),それ以外を背景領域(黒)とした2値画像を作る.これは,上で求めたしきい値を使って,diff_bw = im2bw( diff_gray, thresh );で求まる.

物体領域を求める

最後に,上で求めた2値画像と,物体を含む画像との積を求めることで,物体領域以外は黒にした画像を得ることができる.

for i=1:3
color=a(:,:,i);
color(bw ~= 1)=0;
result(:,:,i)=color;
end

こんな感じ.

まとめ

背景差分は画像処理の基本なので最初に押さえた.コードをまとめると以下のようになる.

img_f=imread( 'input.jpg' );
img_b=imread( 'back.jpg' );
diff = img_f - img_b;
diff_gray = rgb2gray( diff );
thresh = graythresh( diff_gray );
diff_bw = im2bw( diff_gray, thresh );
result = repmat(uint8(0), [size(img_f)] );
for i=1:3
    c=img_f(:,:,i);
    c(diff_bw ~= 1)=0;
    result(:,:,i)=c;
end

【追記】もっと賢いやり方を教えてもらったのでメモ

img_f=imread( 'input.jpg' );
img_b=imread( 'back.jpg' );
diff = img_f - img_b;
diff_gray = rgb2gray( diff );
thresh = graythresh( diff_gray );
diff_bw = im2bw( diff_gray, thresh );
result = img_f .* uint8(repmat( diff_bw, [1 1 3] ));