package imageFiltering.filter; import imageFiltering.*; import java.applet.*; import java.awt.*; import java.awt.event.*; /** * JealousSobelフィルタ */ public class JealousSobel extends Filter { /** * "optimal" 5x5 Filter用 * ノイズを拾いにくい */ private static final double p5[] = {0.036470, 0.248968, 0.429123, 0.248968, 0.036470}; private static final double d5[] = {-0.108385, -0.280349, 0.0, 0.280349, 0.108385}; private static final double Fx5[][] = {{p5[0]*d5[0], p5[0]*d5[1], p5[0]*d5[2], p5[0]*d5[3], p5[0]*d5[4]}, {p5[1]*d5[0], p5[1]*d5[1], p5[1]*d5[2], p5[1]*d5[3], p5[1]*d5[4]}, {p5[2]*d5[0], p5[2]*d5[1], p5[2]*d5[2], p5[2]*d5[3], p5[2]*d5[4]}, {p5[3]*d5[0], p5[3]*d5[1], p5[3]*d5[2], p5[3]*d5[3], p5[3]*d5[4]}, {p5[4]*d5[0], p5[4]*d5[1], p5[4]*d5[2], p5[4]*d5[3], p5[4]*d5[4]}}; private static final double Fy5[][] = {{d5[0]*p5[0], d5[0]*p5[1], d5[0]*p5[2], d5[0]*p5[3], d5[0]*p5[4]}, {d5[1]*p5[0], d5[1]*p5[1], d5[1]*p5[2], d5[1]*p5[3], d5[1]*p5[4]}, {d5[2]*p5[0], d5[2]*p5[1], d5[2]*p5[2], d5[2]*p5[3], d5[2]*p5[4]}, {d5[3]*p5[0], d5[3]*p5[1], d5[3]*p5[2], d5[3]*p5[3], d5[3]*p5[4]}, {d5[4]*p5[0], d5[4]*p5[1], d5[4]*p5[2], d5[4]*p5[3], d5[4]*p5[4]}}; /** * 3x3 Sobel Filter */ private static final double Fx3[][] = {{-0.25, 0.0, 0.25}, {-0.50, 0.0, 0.50}, {-0.25, 0.0, 0.25}}; private static final double Fy3[][] = {{-0.25, -0.50, -0.25}, { 0.0, 0.0, 0.0}, { 0.25, 0.50, 0.25}}; double Fx[][] = Fx5; double Fy[][] = Fy5; private int SN = 1, SNmax = 5, SNmin = 0; private double SAT = 1, SATmax = 5, SATmin = 0; private int HUE = 0, HUEmax = 359, HUEmin = 0; private int MIX = 0, MIXmax = 100, MIXmin = 0; /** 輝度計算のための係数(NTSC係数による加重平均法?) */ double k[] = {0.298912, 0.586611, 0.114478}; /** フィルタサイズの半分 */ int offset = Fx.length/2; /** フィルタの名称を返す */ public String getName() { return "JealousSobel"; } /** 画像のフィルタリング */ public void filter(AnimatedImage AI) { offset = Fx.length/2; double dx, dy, dR, dG, dB, L, H, S, B; AI.repaintAll(); for (int y=0; y=AI.getWidth() || y-offset<0 || y+offset>=AI.getHeight() ) { //画面の端の部分 AI.setRGB( x, y, 0, 0, 0 ); continue; } dR = dG = dB = 0.0; for (int iy=-offset; iy<=offset; iy++) { for (int ix=-offset; ix<=offset; ix++) { dR += AI.getR(x+ix, y+iy) * Fx[iy+offset][ix+offset]; dG += AI.getG(x+ix, y+iy) * Fx[iy+offset][ix+offset]; dB += AI.getB(x+ix, y+iy) * Fx[iy+offset][ix+offset]; } } dx = k[0]*dR + k[1]*dG + k[2]*dB; dR = dG = dB = 0.0; for (int iy=-offset; iy<=offset; iy++) { for (int ix=-offset; ix<=offset; ix++) { dR += AI.getR(x+ix, y+iy) * Fy[iy+offset][ix+offset]; dG += AI.getG(x+ix, y+iy) * Fy[iy+offset][ix+offset]; dB += AI.getB(x+ix, y+iy) * Fy[iy+offset][ix+offset]; } } dy = k[0]*dR + k[1]*dG + k[2]*dB; float HSB[] = java.awt.Color.RGBtoHSB(AI.getR(x, y), AI.getG(x, y), AI.getB(x, y), null); float copy = HSB[2]; HSB[2] = (float)(Math.sqrt(dx*dx+dy*dy)) * (float)SN * (float)0.01; if (HSB[2]> 1) { HSB[2] = 1; } HSB[2] = (float)1.0 - HSB[2]; //輝度成分のみにSobel結果を使用 HSB[2] = HSB[2] * (float)(100 - MIX) * (float)0.01 + copy * (float)MIX * (float)0.01; //元画像とのミキシング HSB[1] = HSB[1] * (float)SAT; if (HSB[1]> 1) { HSB[1] = 1; } //彩度成分を調整 HSB[0] = HSB[0] + ((float)HUE / (float)360); if (HSB[0]>= 1 ) { HSB[0] = HSB[0] - (float)1; } //色相調整 int RGBvalue = java.awt.Color.HSBtoRGB( (float)HSB[0], (float)HSB[1], (float)HSB[2]); AI.setRGB( x, y, ((RGBvalue & 0x00FF0000)>> 16), ((RGBvalue & 0x0000FF00)>> 8), (RGBvalue & 0x000000FF) ); } this.switchThread(); } this.switchThread(); //変更した部分を画面に反映させる AI.repaintAll(); return; } class JealousSobelPanel extends FilterPanel implements AdjustmentListener{ Label L1 = new Label("Sobel"), L2 = new Label("RANGE 5 3"), L3 = new Label("Outline level"), L4 = new Label("Saturation"), L5 = new Label("Hue Wheel"), L6 = new Label("Originality"); TextField T1 = new TextField(""+SN,5), T2 = new TextField(""+SAT,5), T3 = new TextField(""+HUE,5), T4 = new TextField(""+MIX,5); Scrollbar S1 = new Scrollbar(Scrollbar.HORIZONTAL,1,1,0,6), S2 = new Scrollbar(Scrollbar.HORIZONTAL,1,1,0,101), S3 = new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,360), S4 = new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,101); CheckboxGroup g = new CheckboxGroup(); Checkbox cb1 = new Checkbox("5",g, true), cb2 = new Checkbox("3", g,false); JealousSobelPanel(){ this.setLayout(new GridLayout(20,1)); this.add(new Container()); this.add(this.L1); this.add(this.L2); this.add(this.cb1); this.add(this.cb2); this.add(this.L3); this.add(this.S1); this.add(this.T1); this.add(this.L4); this.add(this.S2); this.add(this.T2); this.add(this.L5); this.add(this.S3); this.add(this.T3); this.add(this.L6); this.add(this.S4); this.add(this.T4); S1.addAdjustmentListener(this); S2.addAdjustmentListener(this); S3.addAdjustmentListener(this); S4.addAdjustmentListener(this); } // フィルタのパラメータを取得し設定する public void setFilterParameter(){ Checkbox tmp=g.getSelectedCheckbox(); if(tmp == cb1){ Fx = Fx5; Fy = Fy5; }else if(tmp == cb2){ Fx = Fx3; Fy = Fy3; } try{ MIX = Integer.parseInt(T4.getText()); }catch(NumberFormatException e){} if(MIX> MIXmax) MIX = MIXmax; if(MIX < MIXmin) MIX = MIXmin; T4.setText(""+MIX); try{ HUE = Integer.parseInt(T3.getText()); }catch(NumberFormatException e){} if(HUE> HUEmax) HUE = HUEmax; if(HUE < HUEmin) HUE = HUEmin; T3.setText(""+HUE); try{ SAT = Double.parseDouble(T2.getText()); }catch(NumberFormatException e){} if(SAT> SATmax) SAT = SATmax; if(SAT < SATmin) SAT = SATmin; T2.setText(""+SAT); try{ SN = Integer.parseInt(T1.getText()); }catch(NumberFormatException e){} if(SN> SNmax) SN = SNmax; if(SN < SNmin) SN = SNmin; T1.setText(""+SN); } public void adjustmentValueChanged(AdjustmentEvent e) { int val; Scrollbar se = (Scrollbar) e.getSource(); if(se == S1){ val = S1.getValue(); T1.setText(""+val); } else if(se == S2){ val = S2.getValue(); T2.setText(""+val/20.0); } else if(se == S3){ val = S3.getValue(); T3.setText(""+val); } else if(se == S4){ val = S4.getValue(); T4.setText(""+val); } } } // フィルタパラメータを設定するためのパネルを返す public FilterPanel getFilterPanel(){ return new JealousSobelPanel(); } }

AltStyle によって変換されたページ (->オリジナル) /