画像処理の応用ボリューム–ロールとエッジ検出


ボリュームとは何かについて、ボリュームをどのように理解するかは、ここを参照してください.
http://blog.csdn.net/jia20003/article/details/7038938
一:ローリング
エンボス演算子
1枚のデジタル画像の1次微分結果に対して圧延効果を得ることができて、異なる演算子によって、圧延はまた
凹み効果と凸効果の2種類に分けられます.2つの最も簡単な圧延演算子は:
圧延演算子は双極性演算子とも呼ばれ、1対の画像の寄与は平滑を意味し、-1対の画像の寄与
細部を際立たせることを意味し,最終的には双極性の圧延効果が得られた.
 
プロセス:
a.      画像画素の読み出し
b.      ロール演算子を使用してピクセル配列のボリューム操作を完了
c.      全体的な輝度向上効果–ガウス輝度/しきい値ベース/直接定数向上
 
ロールフィルター効果:左が原図、右がロール処理後の効果
 
二:エッジ抽出
Edge detectionは画像処理において非常に重要であり、非常によく使われる画像処理手段の一つであり、エッジ抽出は
画像の二値化の基本手順の1つです.エッジ抽出は本質的にハイパスフィルタリングであり、デジタル信号の観点から、
高周波信号を保持し、低周波信号を除去するため、エッジ抽出には多くの周波数領域演算子があり、画像をFFTした後
周波数領域でハイパスフィルタリングを完了し、空間領域に移動します.明らかに計算量は比較的に大きくて、空間ドメインの最も経典のエッジ抽出アルゴリズムの
Candy Edge Detectionは非常に良い効果を持っています.
 
ここではレンガを投げて玉を引くだけで、最も簡単なボリュームベースの空間領域エッジ抽出演算子を完成します.演算子は次のとおりです.
 
ボリュームが完了した後の効果は次のとおりです.
グレースケールマップのエッジ抽出が完了すると、次のような効果が得られます.
 
ボリュームベースで画像のシャープ化(Sharp Filter)も可能であり、画像の違いをより明確にすることができる.
簡単なSharp Filterは
 
得られた効果は以下の通りである.
 
ロールオーバーの完了コードは次のとおりです.
	@Override 	public BufferedImage filter(BufferedImage src, BufferedImage dest) { 		int width = src.getWidth();         int height = src.getHeight();          if ( dest == null )             dest = createCompatibleDestImage( src, null );          int[] inPixels = new int[width*height];         int[] outPixels = new int[width*height];         src.getRGB( 0, 0, width, height, inPixels, 0, width ); 		int index = 0; 		int index2 = 0; 		int r=0, g=0, b=0; 		for ( int y = 0; y < height; y++ ) { 			for ( int x = 0; x < width; x++ ) { 				int ta = 255, tr = 0, tg = 0, tb = 0; 				for(int fr = 0; fr < filterRow; fr++) { 					int rowoffset = y + fr; 					if(rowoffset < 0 || rowoffset >=height) { 						rowoffset = y; 					} 					for(int fc = 0; fc < filterCol; fc++) { 						int coloffset = fc + x; 						if(coloffset < 0 || coloffset >= width) { 							coloffset = x; 						} 						index2 = rowoffset * width + coloffset; 						int rgb1 = inPixels[index2]; 						int r1 = (rgb1 >> 16) & 0xff; 						int g1 = (rgb1 >> 8) & 0xff; 						int b1 = rgb1 & 0xff; 						if(isOUT) { 							tr += r1 * outfilter[fr][fc]; 							tg += g1 * outfilter[fr][fc]; 							tb += b1 * outfilter[fr][fc]; 						} else { 							tr += r1 * infilter[fr][fc]; 							tg += g1 * infilter[fr][fc]; 							tb += b1 * infilter[fr][fc]; 						} 					} 				} 				 				tr += COLORCONSTANTS; 				tg += COLORCONSTANTS; 				tb += COLORCONSTANTS; 				r = PixelUtils.clamp(tr); 				g = PixelUtils.clamp(tg); 				b = PixelUtils.clamp(tb); 				outPixels[index] = (ta << 24) | (r << 16) | (g << 8) | b; 				index++; 			} 		}         dest.setRGB( 0, 0, width, height, outPixels, 0, width );         return dest; 	}

単純なエッジ検出を完了するコードは次のとおりです.
	private void filter(int[] inPixels, int[] outPixels, int height, int width, double[][] filterKernel) { 		int index = 0; 		int index2 = 0; 		int r=0, g=0, b=0; 		int semiColumn = filterKernel.length/2; 		int semiRow = filterKernel[0].length/2; 		for ( int y = 0; y < height; y++ ) { 			for ( int x = 0; x < width; x++ ) { 				int ta = 255, tr = 0, tg = 0, tb = 0; 				for(int fr = -semiRow; fr <= semiRow; fr++) { 					int rowoffset = y + fr; 					if(rowoffset < 0 || rowoffset >=height) { 						rowoffset = y; 					} 					for(int fc = -semiColumn; fc <= semiColumn; fc++) { 						int coloffset = fc + x; 						if(coloffset < 0 || coloffset >= width) { 							coloffset = x; 						} 						index2 = rowoffset * width + coloffset; 						int rgb1 = inPixels[index2]; 						int r1 = (rgb1 >> 16) & 0xff; 						int g1 = (rgb1 >> 8) & 0xff; 						int b1 = rgb1 & 0xff; 						tr += ((double)r1 * filterKernel[fr + semiRow][fc + semiColumn]); 						tg += ((double)g1 * filterKernel[fr + semiRow][fc + semiColumn]); 						tb += ((double)b1 * filterKernel[fr + semiRow][fc + semiColumn]); 					} 				} 				 				if(enhanceBrightness) { 					tr += COLORCONSTANTS; 					tg += COLORCONSTANTS; 					tb += COLORCONSTANTS; 				} 				r = PixelUtils.clamp(tr); 				g = PixelUtils.clamp(tg); 				b = PixelUtils.clamp(tb); 				outPixels[index] = (ta << 24) | (r << 16) | (g << 8) | b; 				index++; 			} 		} 	}