2008年6月27日 星期五

OpenCV隨機的實作-隨機分佈的種類

在這裡,要用到的是cvRandArr()這個函式,來介紹隨機分佈的種類--常態分佈(Normal Distribution)與均勻分佈(Uniform Distribution),這兩個的差異在於所有數字的分佈機率不同,而常態分佈(分配)可以定義在很多地方,自然界的狀態大多都屬於常態分佈,因此,在圖形上很多都屬於常態分佈的.

隨機分佈程式碼
#include <cv.h>
#include <highgui.h>


int main()
{
    IplImage *Image1,*Image2;
    CvSize ImageSize1 = cvSize(1000,700);
    Image1 = cvCreateImage(ImageSize1,IPL_DEPTH_8U,3);
    cvZero(Image1);
    Image2 = cvCloneImage(Image1);

    CvRNG rng=cvRNG(cvGetTickCount());

    int RandType1=CV_RAND_UNI;
    int RandType2=CV_RAND_NORMAL;

    CvScalar UniformLowBound=cvScalar(0,0,0,0);
    CvScalar UniformUpBound=cvScalar(255,255,255,0);
    cvRandArr(&rng,Image1,RandType1,UniformLowBound,UniformUpBound);
    cvRandArr(&rng,Image2,RandType2,LowBound,UpBound);

    CvScalar NormalMean=cvScalar(127,127,127,0);
    CvScalar NormalStandard =cvScalar(32,32,32,0);
    cvRandArr(&rng,Image2,RandType2,NormalMean,NormalStandard);

    cvNamedWindow("Random Uniform Distribution",0);
    cvShowImage("Random Uniform Distribution",Image1);
    cvNamedWindow("Random Normal Distribution",0);
    cvShowImage("Random Normal Distribution",Image2);
    cvWaitKey(0);
}

執行結果:


這個程式碼,使用到cvRandArr()這個函數,可以將IplImage資料結構及CvMat資料結構做隨機,而且可以給定隨機分佈的種類,一開始,先初始化Image1的圖形,並將它變成全黑,再複製一份給Image2,設定隨機種子,隨機分佈的種類,Image1給均勻分佈,Image2給常態分佈,給定純量數值(CvScalar),這邊,因為是用Channel為3的RGB圖形,因此cvScalar()的第四個參數不用填,而前三個參數為藍綠紅,在Image1均勻分布的部份是給它隨機的上界及下界,意思就是藍色0~255隨機,綠色0~255隨機,紅色0~255隨機,Image2常態分布的部份是給他平均數跟標準差,這邊平均數是127,標準差是32,標準差不能給太大,因為色彩空間的範圍是0~255,如果標準差給128的話2個標準差涵蓋的是68.26%的出現機率,會超出0~255的範圍,小於0的,大於255的,會各佔15.87%,因此,超出範圍的數字則會全部都卡在0跟255上,將會是錯誤的,要計算的話,最好預設範圍在6個標準差的大小,出現結果將會99%都在0~255的範圍內,常態分佈出現的會是鐘狀分配,均勻分佈則會呈現直線,詳細的內容就要參考統計學相關書籍啦.

均勻分佈                                                   常態分佈



常態分布的標準差
(1) (2)


cvRandArr()
矩陣(CvMat)或圖形(IplImage)隨機出現顏色,這可以模擬雜訊的實作.有兩種參數輸入方式
cvRandArr(CvRNG資料結構,IplImage或CvMat資料結構,均勻分佈參數,隨機範圍下限,隨機範圍上限)
cvRandArr(CvRNG資料結構,IplImage或CvMat資料結構,常態分佈參數,平均數,標準差)




4 意見:

coolwaterld 提到...

hi yester,
问个比较弱的问题:
我用的DEV-cpp
在运行你的程序的时候,总会遇到这样的麻烦:
1
for(int i=0;i<100;i++)需要改为:
int i;
for(int i=0;i<100;i++)
2还有就是默认的参数不能省略:
void cvSet( CvArr* arr, CvScalar value, const CvArr* mask=NULL );
必须写到NULL
我的问题是,怎么关掉这些dev的检查呢?
谢谢

yester 提到...

呵~
我比較偷懶
直接把檔案從"xxx.c"改成"xxx.cpp"兩個問題都解決了...照道理講"xxx.cpp"一定是要使用物件導向C++的函式庫,不過我總是在cpp檔裡面寫C..
也不知道是不是很不好的習慣,如果這樣做會發生什麼問題,那也請多多指教了...

coolwaterld 提到...

呵呵,我试试看。谢谢

Swallow 提到...

这样描出的点好多啊...我不太懂调节那些点分布的多少.感觉想参考你的代码写一个添加高斯噪声的函数,可是 CvInvoke.cvRandArr(ref rng, img, Emgu.CV.CvEnum.RAND_TYPE.CV_RAND_NORMAL, new MCvScalar(127, 127, 127, 0), new MCvScalar(32, 32, 32, 0));
这个函数一出来,图上都开花了,也不知道怎么回事,可以给我讲一下吗?

Copyright 2008-2009,yester