作者VictorTom (鬼翼&娃娃鱼)
看板C_and_CPP
标题Re: [问题] BCB影像处理杂讯
时间Sat Apr 11 03:19:03 2009
※ 引述《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之後:
http://img408.imageshack.us/img408/7915/noise.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
1F:推 devilrucifer:^^板大真的很专业耶~ 小弟也受用不少 04/11 10:25