內插法改寫為SCANLINE(引用JerryKuo版主程式) |
尚未結案
|
dean
一般會員 ![]() ![]() 發表:24 回覆:60 積分:21 註冊:2003-08-23 發送簡訊給我 |
各位前輩好:
小弟根據JerryKuo版主的程式去改寫為SCANLINE,希望能讓速度快一點,因為我想比較內插法與WINDOW提供的COPYRECT速度差異。但小弟更改之後大小有變動,但圖片內容卻卻非我所想要,請指引小弟謝謝!
DWORD BTime; BTime=timeGetTime(); //測試時間 Graphics::TBitmap *Bmp = new Graphics::TBitmap(); Bmp->Assign(Image2->Picture->Bitmap); Graphics::TBitmap *NBmp = new Graphics::TBitmap(); NBmp->PixelFormat=pf24bit; int w,h,newW,newH; double dX,dY,x,y; int i,j; int ix,iy; // integer value of (x,y) double fx,fy; // float value of (x,y) unsigned char clr, clrR,clrG,clrB, nclr1,nclr2,nclr3,nclr4; // color of neighbor 4 pixel w = Bmp->Width; h = Bmp->Height; newW = 50;//StrToInt(Edit1->Text); newH = 50;//StrToInt(Edit2->Text); if((newW <=0) ||(newH <=0)) { ShowMessage("Invalided parameter"); return; } NBmp->Width = newW; NBmp->Height = newH; /* Caculate the step size of movement */ dX = (double)w/(double)newW; dY = (double)h/(double)newH; Byte *ptr_up, *ptr_mid, *ptr_down; for(j = 1 ; j < newH-1 ; j ) { ptr_up=(Byte *)Bmp->ScanLine[j-1]; ptr_mid=(Byte *)Bmp->ScanLine[j]; ptr_down=(Byte *)Bmp->ScanLine[j 1]; for(i =1 ; i < newW-1 ; i ) { x = dX*(double)i; y = dY*(double)j; ix = (int)x; iy = (int)y; fx = x - (float)ix; fy = y - (float)iy; nclr1 = (ptr_mid)[i*3 2]; //GetRValue(Bmp->Canvas->Pixels[ix][iy]); nclr2 = (ptr_down)[i*3 2]; //GetRValue(Bmp->Canvas->Pixels[ix 1][iy]); nclr3 = (ptr_mid)[i*2*3 2]; //GetRValue(Bmp->Canvas->Pixels[ix][iy 1]); nclr4 = (ptr_down)[i*2*3 2]; //GetRValue(Bmp->Canvas->Pixels[ix 1][iy 1]); // Bilinear clrR=(byte)((1.0-fx)*(1.0-fy)*(double)nclr1 (fx)*(1.0-fy)*(double)nclr2 (1.0-fx)* (fy)*(double)nclr3 (fx)* (fy)*(double)nclr4); nclr1 = (ptr_mid)[i*3 1]; //GetGValue(Bmp->Canvas->Pixels[ix][iy]); nclr2 = (ptr_down)[i*3 1]; //GetGValue(Bmp->Canvas->Pixels[ix 1][iy]); nclr3 = (ptr_mid)[i*2*3 1]; //GetGValue(Bmp->Canvas->Pixels[ix][iy 1]); nclr4 = (ptr_down)[i*2*3 1]; //GetGValue(Bmp->Canvas->Pixels[ix 1][iy 1]); // Bilinear clrG=(byte)((1.0-fx)*(1.0-fy)*(double)nclr1 (fx)*(1.0-fy)*(double)nclr2 (1.0-fx)* (fy)*(double)nclr3 (fx)* (fy)*(double)nclr4); nclr1 = (ptr_mid)[i*3]; //GetBValue(Bmp->Canvas->Pixels[ix][iy]); nclr2 = (ptr_down)[i*3]; //GetBValue(Bmp->Canvas->Pixels[ix 1][iy]); nclr3 = (ptr_mid)[i*2*3]; //GetBValue(Bmp->Canvas->Pixels[ix][iy 1]); nclr4 = (ptr_down)[i*2*3]; //GetBValue(Bmp->Canvas->Pixels[ix 1][iy 1]); // Bilinear clrB=(byte)((1.0-fx)*(1.0-fy)*(double)nclr1 (fx)*(1.0-fy)*(double)nclr2 (1.0-fx)* (fy)*(double)nclr3 (fx)* (fy)*(double)nclr4); NBmp->Canvas->Pixels[i][j] = (TColor)RGB(clrR,clrG,clrB); //p1[i][j]=(TColor)RGB(clrR,clrG,clrB); } } Bmp->Width=newW; Bmp->Height=newH; Image2->Picture->Assign(NBmp); Label2->Caption="完 成 速 度 " (IntToStr(timeGetTime()-BTime) " msec."); delete NBmp;感謝指引!< >< > |
arisaka_matsuri
高階會員 ![]() ![]() ![]() ![]() 發表:25 回覆:205 積分:231 註冊:2003-10-19 發送簡訊給我 |
dean 你好:
引言:我想,紅字部分應該就是原因for(j = 1 ; j < newH-1 ; j ) { ptr_up=(Byte *)Bmp->ScanLine[j-1]; ptr_mid=(Byte *)Bmp->ScanLine[j]; ptr_down=(Byte *)Bmp->ScanLine[j 1]; for(i =1 ; i < newW-1 ; i ) { x = dX*(double)i; y = dY*(double)j; .... nclr3 = (ptr_mid)[i*2*3 2]; //GetRValue(Bmp->Canvas->Pixels[ix][iy 1]); .... |
dean
一般會員 ![]() ![]() 發表:24 回覆:60 積分:21 註冊:2003-08-23 發送簡訊給我 |
感謝arisaka_matsuri:
您好!小弟看董您的建議之後,嘗試去更改程式,但仍是不對的結果。
w = Bmp->Width; h = Bmp->Height; newW = 400;//StrToInt(Edit1->Text); newH = 400;//StrToInt(Edit2->Text); NBmp->Width = newW; NBmp->Height = newH; /* Caculate the step size of movement */ dX = (double)w/(double)newW; dY = (double)h/(double)newH; int org=1; Byte *ptr_up, *ptr_mid, *ptr_down; for(j = 1 ; j < newH-1 ; j++) { ptr_up=(Byte *)Bmp->ScanLine[org-1]; ptr_mid=(Byte *)Bmp->ScanLine[org]; ptr_down=(Byte *)Bmp->ScanLine[org+1]; org+=dY; for(i =1 ; i < newW-1 ; i++) { x = dX*(double)i; y = dY*(double)j; ix = (int)x; iy = (int)y; fx = x - (float)ix; fy = y - (float)iy; nclr1 = (ptr_mid)[ix*3+2]; //GetRValue(Bmp->Canvas->Pixels[ix][iy]); nclr2 = (ptr_down)[ix*3+2]; //GetRValue(Bmp->Canvas->Pixels[ix+1][iy]); nclr3 = (ptr_mid)[(ix+1)*3+2]; //GetRValue(Bmp->Canvas->Pixels[ix][iy+1]); nclr4 = (ptr_down)[(ix+1)*3+2]; //GetRValue(Bmp->Canvas->Pixels[ix+1][iy+1]); // Bilinear clrR=(byte)((1.0-fx)*(1.0-fy)*(double)nclr1+(fx)*(1.0-fy)*(double)nclr2 +(1.0-fx)* (fy)*(double)nclr3+(fx)* (fy)*(double)nclr4); nclr1 = (ptr_mid)[ix*3+1]; //GetGValue(Bmp->Canvas->Pixels[ix][iy]); nclr2 = (ptr_down)[ix*3+1]; //GetGValue(Bmp->Canvas->Pixels[ix+1][iy]); nclr3 = (ptr_mid)[(ix+1)*3+1]; //GetGValue(Bmp->Canvas->Pixels[ix][iy+1]); nclr4 = (ptr_down)[(ix+1)*3+1]; //GetGValue(Bmp->Canvas->Pixels[ix+1][iy+1]); // Bilinear clrG=(byte)((1.0-fx)*(1.0-fy)*(double)nclr1+(fx)*(1.0-fy)*(double)nclr2 +(1.0-fx)* (fy)*(double)nclr3+(fx)* (fy)*(double)nclr4); nclr1 = (ptr_mid)[ix*3]; //GetBValue(Bmp->Canvas->Pixels[ix][iy]); nclr2 = (ptr_down)[ix*3]; //GetBValue(Bmp->Canvas->Pixels[ix+1][iy]); nclr3 = (ptr_mid)[(ix+1)*3]; //GetBValue(Bmp->Canvas->Pixels[ix][iy+1]); nclr4 = (ptr_down)[(ix+1)*3]; //GetBValue(Bmp->Canvas->Pixels[ix+1][iy+1]); // Bilinear clrB=(byte)((1.0-fx)*(1.0-fy)*(double)nclr1+(fx)*(1.0-fy)*(double)nclr2 +(1.0-fx)* (fy)*(double)nclr3+(fx)* (fy)*(double)nclr4); NBmp->Canvas->Pixels[i][j] = (TColor)RGB(clrR,clrG,clrB); //p1[i][j]=(TColor)RGB(clrR,clrG,clrB); if (org>Bmp->Height) exit; } }上述的程式結果產生原圖下半部的並沒有內插而得到,且內插出來的效果似乎不好!兩張圖片分別是用版主的原始程式,但處理時間很長,另一張是小弟改寫為SCANLINE的,處理時間較短,但效果很差,而且原圖下半部的並沒有內插而得到。 |
dean
一般會員 ![]() ![]() 發表:24 回覆:60 積分:21 註冊:2003-08-23 發送簡訊給我 |
引言: dean 你好:**我很想學,但又很不懂,所以一直問蠢問題,希望不要不屑我的問題,嘻嘻嘻**引言:我想,紅字部分應該就是原因for(j = 1 ; j < newH-1 ; j ) { ptr_up=(Byte *)Bmp->ScanLine[j-1]; ptr_mid=(Byte *)Bmp->ScanLine[j]; ptr_down=(Byte *)Bmp->ScanLine[j 1]; .... |
arisaka_matsuri
高階會員 ![]() ![]() ![]() ![]() 發表:25 回覆:205 積分:231 註冊:2003-10-19 發送簡訊給我 |
dean 你好:
我實測你改過的程式,可以正常執行沒問題,但是結果不可預期,因為 org += dY; 這個敘述有問題。只要dY有小數點,在相加後 org 會捨棄小數的部分,這就是問題所在。不妨trace看看,會發現 org 不如你想像中那樣,「自動」對應到正確的列。
我用的原理是一樣的,只不過是按照公式直接轉成程式。符號定義如下圖
x = c / G 的寬 / F 的寬 y = r / G 的高 / F 的高 -- (1)而又知 Bilinear 轉換公式為 F(x,y) = F(c,r) = (1-dx) * (1-dy) * G(l,k) + dx * (1-dy) * G(l+1,k) + (1-dx) * dy * G(l,k+1) + dx * dy * G(l+1,k+1) 整理得 F(x,y) = F(c,r) = G(l,k) + (G(l+1,k) - G(l,k)) * dx + (G(l,k+1) - G(l,k)) * dy + (G(l,k) - G(l+1,k+1) - G(l+1,k) - G(l,k+1))) * dx * dy 可以看成是 F(x,y) = F(c,r) = c1 + c2 * dx + c3 * dy + c4 * dx * dy -- (2)就是這麼來的~ |
JerryKuo
版主 ![]() ![]() ![]() ![]() ![]() 發表:42 回覆:571 積分:322 註冊:2003-03-10 發送簡訊給我 |
各位好: billinear內插法使用於影像縮放會有不連續的問題,如果想要讓縮小後的圖片
更有平滑感,建議你們可以加上prediction原理,參考之前的像素,做一個平均
值,考慮到處理速度,以下有幾個做法,參考看看 假設我們要算(x,y)這個點,可用之前已知四點像素值
左上(x-1,y-1),
上方(x, y-1),
右上(x 1,y-1),
左邊(x-1,y)
預測出(x,y)的像素值。 如何預測?
1.最簡單的方法,取平均值avg,當我們用內插法求得(x,y)實際的像素值clr時,
將avg和clr再取平均得realclr,(x,y)的像素值就是realclr。
2.第二個方法,當我們用內插法求得(x,y)實際的像素值clr時,再將clr和已知
四點像素值分別比對,取得和clr最相似的那個像素值clr',再取平均得realclr
就是(x,y)的像素值。 以上是小弟對"內插法使用於縮放影像"的改進方法,參考看看。 ^^
|
dean
一般會員 ![]() ![]() 發表:24 回覆:60 積分:21 註冊:2003-08-23 發送簡訊給我 |
兩位前輩們好:
小弟更改了程式,而程式則是融合JERRYKUO與arisaka_matsuri兩位大哥的程式,下面是程式片段,而小弟也斗膽將兩位大哥的程式拿出比較,請勿見怪!請見圖!
void __fastcall TForm1::Button12Click(TObject *Sender) { DWORD BTime; BTime=timeGetTime(); //測試時間 Graphics::TBitmap *Bmp = new Graphics::TBitmap(); Bmp->Assign(Image2->Picture->Bitmap); Graphics::TBitmap *NBmp = new Graphics::TBitmap(); NBmp->PixelFormat=pf24bit; int w,h,newW,newH; double dX,dY,x,y; int i,j; int ix,iy; // integer value of (x,y) double fx,fy; // float value of (x,y) unsigned char clr, clrR,clrG,clrB, nclr1,nclr2,nclr3,nclr4; // color of neighbor 4 pixel w = Bmp->Width; h = Bmp->Height; newW = 50;//StrToInt(Edit1->Text); newH = 50;//StrToInt(Edit2->Text); if((newW <=0) ||(newH <=0)) { ShowMessage("Invalided parameter"); return; } NBmp->Width = newW; NBmp->Height = newH; /* Caculate the step size of movement */ dX = (double)newW/(double)w; dY = (double)newH/(double)h; Byte **pRef = new Byte *[Bmp->Height]; for(int k = 0; k < Bmp->Height; k ) pRef[k] = (Byte *)Bmp->ScanLine[k]; Byte *ptr; for(j = 0 ; j < newH ; j ) { ptr=(Byte *)NBmp->ScanLine[j]; for(i =0 ; i < newW ; i ) { if (dX<1) x=(double)i/dX dX; else x=(double)i/dX; if (dY<1) y=(double)j/dY dY; else y=(double)j/dY; /*x = dX*(double)i; y = dY*(double)j; */ ix = (int)x; iy = (int)y; fx = x - (float)ix; fy = y - (float)iy; nclr1 = pRef[iy][ix*3 2]; nclr2 = pRef[iy 1][ix*3 2]; nclr3 = pRef[iy][(ix 1)*3 2]; nclr4 = pRef[iy 1][(ix 1)*3 2]; // Bilinear //ptr[i*3 2] = (Byte)(nclr1 nclr2 * fx nclr3 * fy nclr4 * fx * fy); //---- (2) clrR=(byte)((1.0-fx)*(1.0-fy)*(double)nclr1 (fx)*(1.0-fy)*(double)nclr2 (1.0-fx)* (fy)*(double)nclr3 (fx)* (fy)*(double)nclr4); nclr1 = pRef[iy][ix*3 1]; nclr2 = pRef[iy 1][ix*3 1]; nclr3 = pRef[iy][(ix 1)*3 1]; nclr4 = pRef[iy 1][(ix 1)*3 1]; // Bilinear //ptr[i*3 1] = (Byte)(nclr1 nclr2 * fx nclr3 * fy nclr4 * fx * fy); clrG=(byte)((1.0-fx)*(1.0-fy)*(double)nclr1 (fx)*(1.0-fy)*(double)nclr2 (1.0-fx)* (fy)*(double)nclr3 (fx)* (fy)*(double)nclr4); nclr1 = pRef[iy][ix*3]; nclr2 = pRef[iy 1][ix*3]; nclr3 = pRef[iy][(ix 1)*3]; nclr4 = pRef[iy 1][(ix 1)*3]; // Bilinear //ptr[i*3] = (Byte)(nclr1 nclr2 * fx nclr3 * fy nclr4 * fx * fy); clrB=(byte)((1.0-fx)*(1.0-fy)*(double)nclr1 (fx)*(1.0-fy)*(double)nclr2 (1.0-fx)* (fy)*(double)nclr3 (fx)* (fy)*(double)nclr4); ptr[i*3]=clrB; ptr[i*3 1]=clrG; ptr[i*3 2]=clrR; //NBmp->Canvas->Pixels[i][j] = (TColor)RGB(clrR,clrG,clrB); } } Bmp->Width=newW; Bmp->Height=newH; Image2->Picture->Assign(NBmp); Label2->Caption="完 成 速 度 " (IntToStr(timeGetTime()-BTime) " msec."); delete NBmp;裡頭有不好的地方請兩位大哥前輩給小弟指引,謝謝! **我很想學,但又很不懂,所以一直問蠢問題,希望不要不屑我的問題,嘻嘻嘻** |
dean
一般會員 ![]() ![]() 發表:24 回覆:60 積分:21 註冊:2003-08-23 發送簡訊給我 |
引言: 小弟也斗膽將兩位大哥的程式拿出比較,請勿見怪!請見圖! 謝謝! |
arisaka_matsuri
高階會員 ![]() ![]() ![]() ![]() 發表:25 回覆:205 積分:231 註冊:2003-10-19 發送簡訊給我 |
dean 你好:
引言: JERRYKRU版主用的是CANVAS所以比較慢,改為SCANLINE之後應該與arisaka_matsuri一樣快! ...COPYRECT又是用什麼方式去做的? 許多問題,不好意思,因為都是做BILINEAR後發現的!感謝各位前輩給予小弟指引!謝謝先說明計算速度的量測,用timeGetTime()的精確度有限,建議改用QueryPerformanceCounter()。 COPYRECT?被你這麼一提,讓我不禁好奇起來。看完TCanvas::CopyRect()的原始碼,其實就是呼叫StretchBlt()這個WinAPI。不過裡面在賣啥膏藥,得問M$了。我比較了PhotoShop跟Matlab處理bilinear縮小尺寸的結果,並不相同。這就說明同樣用「bilinear」,但是實做的內容還是有不同的地方。我也在IEEE上找了一些paper和其他相關的網頁資料,說明實做上有許多技巧,像是以low pass filter處理再取樣、利用wavelet等等。小弟學的也不多,恐怕無法給予更深入的解答了。如果有那位大大願意分享或提個範例,當然更棒了! |
dean
一般會員 ![]() ![]() 發表:24 回覆:60 積分:21 註冊:2003-08-23 發送簡訊給我 |
引言: 先說明計算速度的量測,用timeGetTime()的精確度有限,建議改用QueryPerformanceCounter()。 COPYRECT?被你這麼一提,讓我不禁好奇起來。看完TCanvas::CopyRect()的原 始碼,其實就是呼叫StretchBlt()這個WinAPI。不過裡面在賣啥膏藥,得問 M$了。我比較了PhotoShop跟Matlab處理bilinear縮小尺寸的結果,並不相同。 這就說明同樣用「bilinear」,但是實做的內容還是有不同的地方。我也在IEEE 上找了一些paper和其他相關的網頁資料,說明實做上有許多技巧,像是以low pass filter處理再取樣、利用wavelet等等。小弟學的也不多,恐怕無法給予更 深入的解答了。如果有那位大大願意分享或提個範例,當然更棒了! 發表人 - jerrykuo 於 2004/05/11 16:02:01arisaka_matsuri大哥您好: 相當感謝您不斷的指引小弟學習,小弟在這邊在次感謝!另外也感謝JerryKuo所提供的範例與改進方法! 在測試的結果,小弟決定使用COPYRECT,他的效果以肉眼來觀看比較好,雖然在論文上沒有辦法解釋如何實作! 如果有哪位大大願意解釋讓我們更清楚COPYRECT,那就太感激了! arisaka_matsuri大哥真的謝謝你,讓我這方面獲益良多! **我很想學,但又很不懂,所以一直問蠢問題,希望不要不屑我的問題,嘻嘻嘻** |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |