Trending News
圖片處理程式的一些問題
最近在做一個圖片處理的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越大 圖就會越小張 我想是我寫錯了
但是不知道哪裡錯誤 請高手幫我一下>"<
感恩
Tai大大:
試了您的解法後 原本的問題還是存在 圖片還是會變得很小張
還是說那個算法本來就會這樣?
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)
恩...
雖然會有圖片隆起的效果 但是圖片的比例(長和寬)會變小
因為
if(x2 >= 0 && y2 >= 0 && x2 <= width && y2 <= height)
隆起效果越明顯時 在這個範圍內的x2和y2會急速縮減導致圖片變得很小張
對了 我想順便問一下
目前我在做素描效果
我先轉黑白→取反色→高斯模糊 然後做color dodge
但是出來的圖片雖然有素描效果 可是黑色的部分會偏綠色
是不是color dodge的部分有錯
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 對應到反色+高斯模糊圖 )
原來是因為綠色的亮度感最大
改成這樣就好了
int avg=(red+green+blue)/3;
out[x] = Color.rgb(avg, avg, avg);
我想嘗試看看第2個 可是看不太懂
那是OpenGL嗎? 怎麼程式碼才幾行就能做到那樣的效果
可不可以幫忙轉成android的語法
拜託了>"
1 Answer
- TaiLv 57 years agoFavorite 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;
}