圖片處理程式的一些問題

最近在做一個圖片處理的app

做到圖片隆起效果時遇到點問題

http://stackoverflow.com/questions/5055625/image-w...

http://stackoverflow.com/questions/5542942/looking...

從上面兩個網頁裡得到這個公式

width = 圖片寬度

height = 圖片長度

r = Sqrt( (x - width/2)^2 + (height/2)^2 )

n = Bulge factor (default = 0)

Set

x' = r^n * ( x - width/2 ) + width/2

y' = r^n * (y - height/2) + height/2

而我寫出來的程式大概是這樣

int color;

for(int x = 0; x < width; x++) {

for(int y = 0; y < height; y++) {

double r = Math.pow(x-width/2, 2) + Math.pow(y-height/2, 2);

double x2 = Math.pow(r, n) * (x - width/2) + (width/2);

double y2 = Math.pow(r, n) * (y - height/2) + (height/2);

if(x2 >= 0 && y2 >= 0 && x2 <= width && y2 <= height){

color = bmp.getPixel((int)x2, (int)y2);//將原圖(x2, y2)的像素取出

pBitmap.setPixel(x, y, color);//將color放入pBitmap(x,y)

}

}

}

但是n越大 圖就會越小張 我想是我寫錯了

但是不知道哪裡錯誤 請高手幫我一下>"<

感恩

Update:

Tai大大:

試了您的解法後 原本的問題還是存在 圖片還是會變得很小張

還是說那個算法本來就會這樣?

Update 2:

r = (x - 0.5)^2 + (y - 0.5)^2

n = Bulge factor (default = 0)

Set

x' = r^n * (x - 0.5) + 0.5

y' = r^n * (y - 0.5) + 0.5

(x and y span from 0 to 1. If your dimensions span 0 to w, replace 0.5 with w/2)

Update 3:

恩...

雖然會有圖片隆起的效果 但是圖片的比例(長和寬)會變小

因為

if(x2 >= 0 && y2 >= 0 && x2 <= width && y2 <= height)

隆起效果越明顯時 在這個範圍內的x2和y2會急速縮減導致圖片變得很小張

Update 4:

對了 我想順便問一下

目前我在做素描效果

我先轉黑白→取反色→高斯模糊 然後做color dodge

但是出來的圖片雖然有素描效果 可是黑色的部分會偏綠色

是不是color dodge的部分有錯

Update 5:

red = Math.min(255, red+(red*red2)/(255 - red2));

green = Math.min(255, green+(green*green2)/(255 - green2));

blue = Math.min(255, blue+(blue*blue2)/(255 - blue2));

out[x] = Color.rgb(red, green, blue);

(red、green、blue 對應到黑白圖 ;red2、green2 、blue2 對應到反色+高斯模糊圖 )

Update 6:

原來是因為綠色的亮度感最大

改成這樣就好了

int avg=(red+green+blue)/3;

out[x] = Color.rgb(avg, avg, avg);

Update 7:

我想嘗試看看第2個 可是看不太懂

那是OpenGL嗎? 怎麼程式碼才幾行就能做到那樣的效果

可不可以幫忙轉成android的語法

拜託了>"

1 Answer

Rating
  • Tai
    Lv 5
    7 years ago
    Favorite Answer

    要反過來求解

    假設

    center = (w/2, h/2) = (x0, y0) = p0

    given p' = (x,y)

    solve the unknown p

    |p'-p0| = R = r^n

    |p-p0| = r = R^ (1/n)

    p = p0 + (p'-p0) R^(-1+1/n) <= ans

    code:

    double x0 = width/2.0, y0 = height/2.0;

    double R = Math.pow( (x-x0)*(x-x0)+(y-y0)*(y-y0), 0.5); // |p'-p0|

    double x2 = Math.pow(r, -1.0 + 1.0/n) + x0;

    double y2 = Math.pow(r, -1.0 + 1.0/n) + y0;

    if(x2 >= 0 && y2 >= 0 && x2 <= width && y2 <= height){

    color = bmp.getPixel((int)x2, (int)y2);//將原圖(x2, y2)的像素取出

    pBitmap.setPixel(x, y, color);//將color放入pBitmap(x,y)

    2013-11-08 20:53:42 補充:

    code 打錯了, 更正為

    double x0 = width/2.0, y0 = height/2.0;

    double R = Math.pow( (x-x0)*(x-x0)+(y-y0)*(y-y0), 0.5); // |p'-p0|

    double x2 = (x-x0) * Math.pow(R, -1.0 + 1.0/n) + x0;

    double y2 = (y-y0) * Math.pow(R, -1.0 + 1.0/n) + y0;

    沒環境驗證, 祝你順利

    2013-11-09 04:01:17 補充:

    更正為 p'=(x,y), p is unknown

    let

    |p'-p0| = R

    |p-p0| = r

    p'-p0 = r^n (p-p0)

    => R=|p'-p0| = |r^n (p-p0)| = r^n * r = r^(n+1)

    => r = R^(1/(n+1))

    => p = (p'-p0) * R^(-n/(n+1)) + p0

    code:

    double x2 = (x-x0) * Math.pow(R, -n/(n+1.)) + x0;

    double y2 = (y-y0) * Math.pow(R, -n/(n+1.)) + y0;

    2013-11-09 04:07:04 補充:

    版大的公式是將 image 長寬正規化為 1 後,

    原本網格 (x,y) 會以中心 (.5, 0.5) 向外膨脹.

    膨脹的是 "網格"

    如果上色系統是根據新網格, 和網格上的顏色重新上色,

    那會看到圖片隆起的效果

    但原式中 (x2,y2) 是 (x,y) 膨脹的新位置.

    將膨脹後的位置的顏色放到 (x,y), 反而給人陷下去的感覺.

    所以是反過來, (x,y) 是膨脹後的網點,

    找某個 (x2,y2) 能膨脹到 (x,y), 在取 (x2,y2) 的顏色給 (x,y)

    2013-11-10 11:35:21 補充:

    是說 (x2,y2) 在原圖範圍越來越小吧?

    與這無關 f(x2 >= 0 && y2 >= 0 && x2 <= width && y2 <= height)

    你說的 source code, 我也覺得很奇怪, 就是向外膨脹, 沒有越到邊界膨脹越少的特行.

    但為什有這種效果 ....

    2013-11-10 19:58:24 補充:

    http://stackoverflow.com/questions/5055625/image-w...

    中提供兩式, 第一個我仍覺得是膨脹網格

    就算逆算, 也只是你說的在原圖範圍越來越小

    第二個用 p = p' - nlog( d ) v.

    n = 0, 沒有變形.

    n 逐漸變大時,

    同張圖內, d 落在 sqrt(2) >1>d>0 範圍內.

    越靠近圖心扭曲越大, 到 d=1 扭曲最小 log(d)=0.

    而 d>1 後是反向, 但變動不大.

    用第二式符合你需求

    2013-11-11 15:26:55 補充:

    程式 2 是 GLSL, 算是跟 OpenGL 搭配用的 shader code.

    看似 fragment shader, 也就是寫每個 pixel 的處理程式.

    所以比較短 ..

    2013-11-11 15:27:50 補充:

    版大, 我昨晚應該有寄到你信箱喔.

    意見區和輔助回答區字數限制太誇張, 根本寫不下去

    2013-11-12 05:00:20 補充:

    適合版大的第二式, 以 opencv

    http://stackoverflow.com/questions/5055625/image-w...

    Mat im = imread("lina.png");

    Mat warp(im.size(), im.type());

    imshow("warp", warp); waitKey(0);

    int width = im.cols, height = im.rows;

    double x0, y0, w2, h2;

    2013-11-12 05:02:47 補充:

    x0 = width/2., y0 = height/2.;

    w2 = width/1.4, h2 = height/1.4;

    for-loop, 則外部用 n = 0:0.2:0.01

    內部就是跑 y,x

    每次新 n 值, warp.setTo(Scalar(255,255,255));

    2013-11-12 05:04:15 補充:

    Point2d cen((x-x0)/w2,(y-y0)/h2);

    double len=sqrt(cen.ddot(cen));

    double nlog=n*log(len);

    Point2d mcen = nlog*cen;

    int x2=x-mcen.x*w2;

    int y2=y-mcen.y*h2;

    if(x2 >= 0 && y2 >= 0 && x2 < width && y2 < height){

    Vec3b color = im.at (y2, x2);

    warp.at (y, x) = color;

    }

Still have questions? Get your answers by asking now.