Re: [問題] BCB影像處理雜訊

看板C_and_CPP作者 (鬼翼&娃娃魚)時間16年前 (2009/04/10 19:19), 編輯推噓1(100)
留言1則, 1人參與, 最新討論串2/3 (看更多)
※ 引述《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

04/11 10:25, , 1F
^^板大真的很專業耶~ 小弟也受用不少
04/11 10:25, 1F
文章代碼(AID): #19tvkeaw (C_and_CPP)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 3 篇):
文章代碼(AID): #19tvkeaw (C_and_CPP)