Re: [問題] BCB影像處理雜訊
※ 引述《yanqinru (髍鵀)》之銘言:
: 各位板友好
: 小弟是剛學影像處理的新手
: 目前在研究雜訊程式碰到了許多問題
: 雖然有對照書本寫的雜訊公式來看
: 可是還是不知道以下三段程式是怎麼做加入雜訊運算
老實說小弟有點懶得看他的code了, 因為有些數學計算在裡面....
不同的design思維也許會有不一樣的寫法, 公式也可能因此變化....
剛好以前小弟作業寫過Noise Generation, 所以就野人獻曝一下....
看您會不會比較容易看懂, 因為我的公式都是書上直接打上來的....
幾年前實作的, 若有漏誤的地方, 也請板上其他先進不吝指教....
先說, 小弟是參考Prentice Hall出版, 作者 Rafael 與 Richard
的 Digital Image Processing 2nd, ISBN: 0-13-094650-8 (原文)
http://gist.github.com/93196
這是小弟作業的一個function, 用來將已經輸入的gray level影像加入雜訊....
所以有些變數function內可能沒看到宣告, 那是因為放在.h檔裡....
我已經盡量注意加補才上傳code, 只是像Source/Target Image的data等懶得加....
SourceRaw[]已存好Image的gray level, 只是展開成一維陣列(unsigned char)
TargetRaw[]是加入Noise後的Image要存入的地方; TargetSize是總pixel數....
choice是要加入的Noise種類, 有實作的Noise為書本上介Ch5.2 p.224的那六種....
r1與r2是雜訊的參數, 大部份的情況r1為mean, r2為Variance....
在某些Noise Model參數比較不同, 這點就自己對書看或者直接看註解吧^^||
PS. 請不用理會那個回傳值, 那是作業裡function的design架構....
==
實作概念:
照書本提供的機率密度函數, 先算出一個pixel變化為原值-255~+255的機率分布(PDF[])
for i從第一到最後一個pixel一遍, 用亂數算出0.0~1.0的機率值, 決定level變化....
將原始SourceRaw[i]裡的level加上變化值, 處理邊界判斷後, 寫進TargetRaw[i]去....
至於為何需要CPDF[], 是為了將在0.0~1.0的亂數拿去依照原來的PDF[]查表用的....
實作流程:
1.依照機率模型與其對應函數, 產生PDF[]與CPDF[].
2.for i產生0.0~1.0的亂數值, 找到對應CPDF的index k.
3.將SourceRaw[i] + k的結果寫到TargetRaw[i]並clamp.
4.持續2.直接TargetSize的所有pixels都被處理完.
其他我就不知道要補充什麼了, 當然應該還有其他的design concept....
不過我的想法, 在產生PDF[]那邊, 應該主要計算都match書上的公式....
Impulse小弟我比較沒把握, 因為Pa和Pb我不確定是總合為1.0還是各自到1.0....
它的r1即Pa, r2即Pb, 要是機率密度總合超過1.0, 我就不知道該怎麼算它了Orz
==
<恕刪>
: 以上幾個問題煩請板友幫小弟解惑
: 不好意思一次問太多問題了...
: 小弟僅能盡量以微薄的P幣答謝回答問題的板友
: 感謝大家
複習自己寫過的一小段程式果然比看別人的程式容易一些XD
如同小弟回覆您mail寫的, 要寫加入雜訊的功能....
建議您把Show Histogram的功能先寫出來會比較好....
下面就貼幾張貼圖好了, 因為我不確定我們是否是同一本書....
原圖(來自書本): http://img382.imageshack.us/img382/2894/fig503l.png


分別是由原圖加入六種Noise, 由左至右給的參數應該是:
1. MV=10, V=100; 2. 同#1; 3. MV=10, V=20; 4.MV=20, V=400;
5. 同#1; 6. Upper Ratio=5%, Lower Ratio=5%
==
好像有板友建議也直接貼code, 也好, 貼code網站好像少最後幾行@_@"
unsigned long ImageProcess::Noise(int choice, double r1, double r2)
{
//Probability Density Functions and pointers for Noises .
double PDF[511], CPDF[511], *P, *CP;
//Pick the random number seed by time .
time_t t;
srand((unsigned) time(&t));
//Compute Probability Density Functions by choice type .
switch(choice)
{
case 1: //Gaussian Noise .
{ //Use {} to prevent errors for declaring variables in case .
double MV, SD, V; //MV: Mean Value; SD: Standard Deviation; V:
Variance = SD^2 .
MV = r1;
V = r2;
if(V < 0.) return 0; //Error handle for negative Variance .
else SD = sqrt(V);
//Compute the probability of a GrayLevel changing its value to other
level .
if(V != 0.)
for(int i=-255; i<=255; i++)
P[i] = exp(-(i-MV)*(i-MV)/(2.*V)) / (sqrt(2.*PI)*SD);
//Only shift when Variance is zero .
else
{
for(int j=-255; j<=255; j++) P[j] = 0.;
if(MV < -255) P[-255] = 1.;
else if(MV > 255 || (MV+0.5) > 255) P[255] = 1.;
else P[(int)(MV+0.5)] = 1.;
}
}break;
case 2: //Rayleigh Noise .
{ //Use {} to prevent errors for declaring variables in case .
double A, B, MV, V; //MV: Mean Value; V: Variance = SD^2 .
MV = r1;
V = r2;
if(V < 0.) return 0; //Error handle for negative Variance .
//Compute the parameters A and B of Rayleigh model .
B = 4 * V / (4 - PI);
A = MV - sqrt(PI * B / 4);
//Compute the probability of a GrayLevel changing its value to other
level .
for(int i=-255; i<=255; i++)
P[i] = i >= A ? 2.*(i-A)*exp(-(i-A)*(i-A)/B) / B : 0.;
}break;
case 3: //Erlang Noise .
{ //Use {} to prevent errors for declaring variables in case .
double A, MV, V, factorial = 1.; //MV: Mean Value; V: Variance = SD^2 .
unsigned long B;
MV = r1;
V = r2;
if(MV <= 0. || V <= 0.) return 0;
//Compute the parameters A and B of Erlang model .
A = MV / V;
B = A * MV + 0.5;
A = B / MV;
if(A <= 0. || B < 1) return 0;
for(unsigned long i=B-1; i>1; i--) factorial *= i;
for(int j=-255; j<=0; j++) P[j] = 0.;
//Compute the probability of a GrayLevel changing its value to other
level .
for(int k=1; k<=255; k++) P[k] = (pow(A, B)*pow(k, B-1) / factorial) *
exp(-A*k);
}break;
case 4: //Exponential Noise .
{ //Use {} to prevent errors for declaring variables in case .
double A, MV, V; //MV: Mean Value; V: Variance = SD^2 .
MV = r1;
if(MV <= 0.) return 0;
//Compute the parameters A of Exponential model (B = A^2) .
A = 1 / MV;
//Compute the probability of a GrayLevel changing its value to other
level .
for(int i=-255; i<0; i++) P[i] = 0.;
for(int j=0; j<=255; j++) P[j] = A * exp(-A*j);
}break;
case 5: //Uniform Noise .
{ //Use {} to prevent errors for declaring variables in case .
double temp, MV, V; //MV: Mean Value; V: Variance = SD^2 .
int A, B;
MV = r1;
V = r2;
if(V < 0.) return 0; //Error handle for negative Variance .
//Compute the parameters A and B of Uniform model .
temp = MV - sqrt(3. * V);
A = temp >= 0. ? temp + 0.5 : temp - 0.5;
temp = MV + sqrt(3. * V);
B = temp >= 0. ? temp + 0.5 : temp - 0.5;
//Compute the probability of a GrayLevel changing its value to other
level .
if(A != B)
for(int i=-255; i<=255; i++)
P[i] = (A <= i && i <= B) ? 1. / (B - A) : 0.;
//Only shift when Variance is zero .
else
{
for(int j=-255; j<=255; j++) P[j] = 0.;
if(A < -255) P[-255] = 1.;
else if(B > 255) P[255] = 1.;
else P[A] = 1.;
}
}break;
case 6: //Impulse Noise .
{ //Use {} to prevent errors for declaring variables in case .
double A, B, temp;
//A, B directly get probability by parameters of Noise() .
A = r1;
B = r2;
if(A < 0. || B < 0.) return 0; //Error handle for negative probability
.
//Compute the probability of a GrayLevel changing its value to other
level .
for(int i=-255; i<=255; i++) P[i] = 0.;
temp = A + B;
if(temp <= 1.)
{
P[-255] = A;
P[0] = 1. - (temp);
P[255] = B;
}
//Special case for the total probability A + B > 1 .
else
{
P[-255] = A / temp;
P[255] = B / temp;
}
}break;
default: return 0; //Return 0 for handling error choice type .
}
//Make Counted Probability tables .
CP[-255] = P[-255];
if(choice != 6)
{
for(int i=-254; i<=255; i++)
{
CP[i] = CP[i-1] + P[i];
//Special process to prevent errors occured by floating point .
if((CP[i] > 0.9995 && CP[i] == CP[i-1]) || CP[i] >= 1.)
while(i <= 255) CP[i++] = 1.;
}
}
//Special case for Impulse Noise to prevent error displaying .
else
{
for(int i=-254; i<=255; i++) CP[i] = 0.;
CP[0] = CP[-255] + P[0];
CP[255] = CP[0] + P[255];
}
//Generate the image added Noise by CPDF[] .
int result; //Result of changing Graylevel .
unsigned long rv1, rv2, rv3; //Use 3 1-byte random numbers combining
3-bytes random numbers .
double RV, R_MAX = 0x00FFFFFFU; //RV: Random Value from 0. to 1; R_MAX:
the max of 3-bytes random numbers .
for(unsigned long j=0; j<TargetSize; j++)
{
//Generate 3-bytes random numbers and shrink to 0. ~ 1 .
rv1 = rand() & 0x00FFU;
rv2 = rand() & 0x00FFU;
rv3 = rand() & 0x00FFU;
RV = ((rv1<<16) | (rv2<<8) | rv3) / R_MAX; //Extend MAX of RAND form
0x7FFFU to 0x00FFFFFFU .
//Generate changing Graylevel .
result = SourceRaw[j] + 255;
for(int k=-255; k<=254; k++)
if(CP[k] > RV)
{
result = SourceRaw[j] + k;
break;
}
//Fix to 0 ~ 255 and assign to TargetImage .
if(result < 0) TargetRaw[j] = 0;
else if(result > 255) TargetRaw[j] = 255;
else TargetRaw[j] = result;
}
return TargetSize;
}
//---------------------------------------------------------------------------
--
深夜不睡覺在這邊騙P幣, 早上起不來去拍SG該怎麼辦啊....>_<#
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.132.174.98
推
04/11 10:25, , 1F
04/11 10:25, 1F
討論串 (同標題文章)