画像処理の移動ブラー
5585 ワード
- created by gloomyfish
ボリュームブラーまたはボリュームスムーズフィルタリングは、画像ノイズを除去したり、一般的な画像ブラーの特効を生じたりすることができるが、
モバイル・ファジイの特効もボリュームベースであり、Box Blurに比べてGaussian Blurのアルゴリズムでは、モバイル・ファジイは完了するだけである.
1回の1次元ボリュームは、1次元ボリュームの完了とは異なり、水平と垂れではなく一定の角度に基づいています.
2つの方向にまっすぐ.ファジイの1 Dボリュームを移動するには、次の3つの要因を考慮します.
a.操作数の多少-即ち距離(Distance)
b.1次元オペランドの画素配列における移動方向、すなわち角度(Angle)
c.一次元オペランドの影引き効果–すなわちScale(拡大と縮小の程度)(Zoom/Scale)
距離と角度の関係は、三角ジオメトリで次のように表すことができます.
距離と角度が既知であることを想定して中心点(ターゲット画素点)を知ると、各オペランドの画素点座標、偽を求めることができる
中心点座標をBase(x 0,y 0)とすると、オペランドP(a,b)の座標式は次のように表される.
a = sinx * c +y0
b = cosx * c +x0
縮小機能は実はXYの2つの方向で画像に対して1次元の画素を計算して結合して、更にこれらの画素の平均値を求めます
すなわち、中心点画素がx 0、y 0、縮退防止比率がs 0であると仮定すると、オペランド毎の画素点座標は以下のように表すことができる.
a= x0-x0 * s0 + a
b= y0-y0*so + b
原理部分の解釈はおおよそそうであるが,次に,実際の画像処理効果とソースコードの詳細な解釈を見る.
プログラムの実行効果は次のとおりです.距離50ピクセル、角度0の場合:
角度30時のフィルター運転結果:
ブラー効果の縮小:
角度、距離、縮小の3つのパラメータの総合効果:
キーコードの説明:
三角ジオメトリ角度sinとcosの値を計算するコードは次のとおりです.
計算距離半径コードは次のとおりです.
オペランドのピクセル座標を計算するコードは次のとおりです.
Scaleを完了するコードは次のとおりです.
ピクセルの平均値を求め、1次元ボリュームを完了するコードは以下の通りです.
ターゲットピクセルを再入力するコードは次のとおりです.
ファジイアルゴリズムを移動する完全なソースコードは次のとおりです(テストコードは含まれません).
後記:本フィルタの基点である中心画素は、調整可能です.興味のある方は自分で作成してください.
ボリュームブラーまたはボリュームスムーズフィルタリングは、画像ノイズを除去したり、一般的な画像ブラーの特効を生じたりすることができるが、
モバイル・ファジイの特効もボリュームベースであり、Box Blurに比べてGaussian Blurのアルゴリズムでは、モバイル・ファジイは完了するだけである.
1回の1次元ボリュームは、1次元ボリュームの完了とは異なり、水平と垂れではなく一定の角度に基づいています.
2つの方向にまっすぐ.ファジイの1 Dボリュームを移動するには、次の3つの要因を考慮します.
a.操作数の多少-即ち距離(Distance)
b.1次元オペランドの画素配列における移動方向、すなわち角度(Angle)
c.一次元オペランドの影引き効果–すなわちScale(拡大と縮小の程度)(Zoom/Scale)
距離と角度の関係は、三角ジオメトリで次のように表すことができます.
距離と角度が既知であることを想定して中心点(ターゲット画素点)を知ると、各オペランドの画素点座標、偽を求めることができる
中心点座標をBase(x 0,y 0)とすると、オペランドP(a,b)の座標式は次のように表される.
a = sinx * c +y0
b = cosx * c +x0
縮小機能は実はXYの2つの方向で画像に対して1次元の画素を計算して結合して、更にこれらの画素の平均値を求めます
すなわち、中心点画素がx 0、y 0、縮退防止比率がs 0であると仮定すると、オペランド毎の画素点座標は以下のように表すことができる.
a= x0-x0 * s0 + a
b= y0-y0*so + b
原理部分の解釈はおおよそそうであるが,次に,実際の画像処理効果とソースコードの詳細な解釈を見る.
プログラムの実行効果は次のとおりです.距離50ピクセル、角度0の場合:
角度30時のフィルター運転結果:
ブラー効果の縮小:
角度、距離、縮小の3つのパラメータの総合効果:
キーコードの説明:
三角ジオメトリ角度sinとcosの値を計算するコードは次のとおりです.
// calculate the trianglegeometry value float sinAngle = (float)Math.sin(angle/180.0f * onePI); float coseAngle = (float)Math.cos(angle/180.0f * onePI);
計算距離半径コードは次のとおりです.
// calculate the distance,same as box blur float imageRadius = (float)Math.sqrt(cx*cx + cy*cy); float maxDistance = distance + imageRadius * zoom;
オペランドのピクセル座標を計算するコードは次のとおりです.
// calculate the operatorsource pixel if(distance > 0) { newY = (int)Math.floor((newY+ i*sinAngle)); newX = (int)Math.floor((newX + i*coseAngle)); }
Scaleを完了するコードは次のとおりです.
// scale the pixels float scale = 1-zoom*f; m11 = cx - cx*scale; m22 = cy - cy*scale; newY = (int)(newY * scale +m22); newX = (int)(newX * scale + m11);
ピクセルの平均値を求め、1次元ボリュームを完了するコードは以下の通りです.
// blur the pixels, here count++; int rgb= inPixels[newY*width+newX]; ta += (rgb >> 24) & 0xff; tr += (rgb >> 16) & 0xff; tg += (rgb >> 8) & 0xff; tb += rgb & 0xff;
ターゲットピクセルを再入力するコードは次のとおりです.
ta = clamp((int)(ta/count)); tr = clamp((int)(tr/count)); tg = clamp((int)(tg/count)); tb = clamp((int)(tb/count)); outPixels[index] = (ta << 24) | (tr<< 16) | (tg << 8) | tb;
ファジイアルゴリズムを移動する完全なソースコードは次のとおりです(テストコードは含まれません).
package com.gloomyfish.process.blur.study; import java.awt.image.BufferedImage; public class MotionFilter { private float distance = 0;// default; private float onePI = (float)Math.PI; private float angle = 0.0f; private float zoom = 0.4f; public float getDistance() { return distance; } public void setDistance(float distance) { this.distance = distance; } public float getAngle() { return angle; } public void setAngle(float angle) { this.angle = angle; } public BufferedImage filter(BufferedImage src, BufferedImage dst) { int width = src.getWidth(); int height = src.getHeight(); if ( dst == null ) dst = createCompatibleDestImage( src, null ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; getRGB( src, 0, 0, width, height, inPixels ); int index = 0; int cx = width/2; int cy = height/2; // calculate the triangle geometry value float sinAngle = (float)Math.sin(angle/180.0f * onePI); float coseAngle = (float)Math.cos(angle/180.0f * onePI); // calculate the distance, same as box blur float imageRadius = (float)Math.sqrt(cx*cx + cy*cy); float maxDistance = distance + imageRadius * zoom; int iteration = (int)maxDistance; for(int row=0; row 0) { newY = (int)Math.floor((newY + i*sinAngle)); newX = (int)Math.floor((newX + i*coseAngle)); } float f = (float)i/iteration; if (newX < 0 || newX >= width) { break; } if (newY < 0 || newY >= height) { break; } // scale the pixels float scale = 1-zoom*f; m11 = cx - cx*scale; m22 = cy - cy*scale; newY = (int)(newY * scale + m22); newX = (int)(newX * scale + m11); // blur the pixels, here count++; int rgb = inPixels[newY*width+newX]; ta += (rgb >> 24) & 0xff; tr += (rgb >> 16) & 0xff; tg += (rgb >> 8) & 0xff; tb += rgb & 0xff; } // fill the destination pixel with final RGB value if (count == 0) { outPixels[index] = inPixels[index]; } else { ta = clamp((int)(ta/count)); tr = clamp((int)(tr/count)); tg = clamp((int)(tg/count)); tb = clamp((int)(tb/count)); outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb; } index++; } } setRGB( dst, 0, 0, width, height, outPixels ); return dst; } public int clamp(int c) { if (c < 0) return 0; if (c > 255) return 255; return c; } }
後記:本フィルタの基点である中心画素は、調整可能です.興味のある方は自分で作成してください.