整理图像的高斯金字塔用java编写的.docx
《整理图像的高斯金字塔用java编写的.docx》由会员分享,可在线阅读,更多相关《整理图像的高斯金字塔用java编写的.docx(22页珍藏版)》请在冰点文库上搜索。
整理图像的高斯金字塔用java编写的
一:
图像金字塔基本操作
对一张图像不断的模糊之后向下采样,得到不同分辨率的图像,同时每次得到的
新的图像宽与高是原来图像的1/2,最常见就是基于高斯的模糊之后采样,得到的
一系列图像称为高斯金字塔。
高斯金字塔不同(DoG)又称为拉普拉斯金字塔,其计算公式如下:
L(i)=G(i)–expand(G(i+1))
第i层拉普拉斯金字塔是由第i层高斯金字塔减去第i+1层高斯金字塔expand之后得到。
本文得到的DoG(DifferenceofGaussian)结果如下:
二:
关键代码解析
金字塔reduce操作实现代码如下:
[java]viewplaincopy
1privateBufferedImagepyramidReduce(BufferedImagesrc){
2intwidth=src.getWidth();
3intheight=src.getHeight();
4BufferedImagedest=createSubCompatibleDestImage(src,null);
5int[]inPixels=newint[width*height];
6intow=width/2;
7intoh=height/2;
8int[]outPixels=newint[ow*oh];
9getRGB(src,0,0,width,height,inPixels);
10intinRow=0,inCol=0,index=0,oudex=0,ta=0;
11float[][]keneralData=this.getHVGaussianKeneral();
12for(introw=0;row13for(intcol=0;col14inRow=2*row;
15inCol=2*col;
16if(inRow>=height){
17inRow=0;
18}
19if(inCol>=width){
20inCol=0;
21}
22floatsumRed=0,sumGreen=0,sumBlue=0;
23for(intsubRow=-2;subRow<=2;subRow++){
24intinRowOff=inRow+subRow;
25if(inRowOff>=height||inRowOff<0){
26inRowOff=0;
27}
28for(intsubCol=-2;subCol<=2;subCol++){
29intinColOff=inCol+subCol;
30if(inColOff>=width||inColOff<0){
31inColOff=0;
32}
33index=inRowOff*width+inColOff;
34ta=(inPixels[index]>>24)&0xff;
35intred=(inPixels[index]>>16)&0xff;
36intgreen=(inPixels[index]>>8)&0xff;
37intblue=inPixels[index]&0xff;
38sumRed+=keneralData[subRow+2][subCol+2]*red;
39sumGreen+=keneralData[subRow+2][subCol+2]*green;
40sumBlue+=keneralData[subRow+2][subCol+2]*blue;
41}
42}
43
44oudex=row*ow+col;
45outPixels[oudex]=(ta<<24)|(clamp(sumRed)<<16)|(clamp(sumGreen)<<8)|clamp(sumBlue);
46}
47}
48setRGB(dest,0,0,ow,oh,outPixels);
49returndest;
50}
金字塔expand实现代码如下:
[java]viewplaincopy
51publicBufferedImagepyramidExpand(BufferedImagesrc){
52intwidth=src.getWidth();
53intheight=src.getHeight();
54int[]inPixels=newint[width*height];
55getRGB(src,0,0,width,height,inPixels);
56intow=2*width;
57intoh=2*height;
58int[]outPixels=newint[ow*oh];
59intindex=0,outdex=0,ta=0;
60float[][]keneralData=this.getHVGaussianKeneral();
61BufferedImagedest=createTwiceCompatibleDestImage(src,null);
62for(introw=0;row63for(intcol=0;col64floatsumRed=0,sumGreen=0,sumBlue=0;
65for(intsubRow=-2;subRow<=2;subRow++){
66doublesrcRow=(row+subRow)/2.0;
67doublej=Math.floor(srcRow);
68doublet=srcRow-j;
69if(t>0){
70continue;
71}
72if(srcRow>=height||srcRow<0){
73srcRow=0;
74}
75for(intsubCol=-2;subCol<=2;subCol++){
76doublesrcColOff=(col+subCol)/2.0;
77j=Math.floor(srcColOff);
78t=srcColOff-j;
79if(t>0){
80continue;
81}
82if(srcColOff>=width||srcColOff<0){
83srcColOff=0;
84}
85index=(int)(srcRow*width+srcColOff);
86ta=(inPixels[index]>>24)&0xff;
87intred=(inPixels[index]>>16)&0xff;
88intgreen=(inPixels[index]>>8)&0xff;
89intblue=inPixels[index]&0xff;
90sumRed+=keneralData[subRow+2][subCol+2]*red;
91sumGreen+=keneralData[subRow+2][subCol+2]*green;
92sumBlue+=keneralData[subRow+2][subCol+2]*blue;
93}
94}
95outdex=row*ow+col;
96outPixels[outdex]=(ta<<24)|(clamp(4.0f*sumRed)<<16)|(clamp(4.0f*sumGreen)<<8)|clamp(4.0f*sumBlue);
97//outPixels[outdex]=(ta<<24)|(clamp(sumRed)<<16)|(clamp(sumGreen)<<8)|clamp(sumBlue);
98}
99}
100setRGB(dest,0,0,ow,oh,outPixels);
101returndest;
102}
图像金字塔的reduce与expand过程都是卷积采样实现。
特别注意的是expand操作不是reduce的可逆操作。
关于什么是卷积,高斯滤波请参见博客上的其它相关文章。
高斯金字塔全部算法源代码如下:
[java]viewplaincopy
103packagecom.gloomyfish.image.pyramid;
104
105importjava.awt.image.BufferedImage;
106importjava.awt.image.ColorModel;
107
108publicclassPyramidAlgorithmextendsGaussianFilter{
109privatefloata;
110
111publicPyramidAlgorithm(){
112a=0.4f;
113}
114
115publicvoidsetParameter(floatp){
116this.a=p;
117}
118
119publicBufferedImage[]pyramidDown(BufferedImagesrc,intlevel){
120BufferedImage[]imagePyramids=newBufferedImage[level+1];
121imagePyramids[0]=src;
122for(inti=1;i123imagePyramids[i]=pyramidReduce(imagePyramids[i-1]);
124}
125returnimagePyramids;
126}
127
128publicBufferedImage[]pyramidUp(BufferedImage[]srcImage){
129BufferedImage[]imagePyramids=newBufferedImage[srcImage.length];
130for(inti=0;i131imagePyramids[i]=pyramidExpand(srcImage[i]);
132}
133returnimagePyramids;
134}
135
136/***
137*l1=g1-expand(g2)
138*l2=g2-expand(g3)
139*l0=g0-expand(g1)
140*@paramreduceImages
141*@paramexpandImages
142*@return
143*/
144publicBufferedImage[]getLaplacianPyramid(BufferedImage[]reduceImages){
145BufferedImage[]laplaciImages=newBufferedImage[reduceImages.length-1];
146for(inti=1;i147BufferedImageexpandImage=pyramidExpand(reduceImages[i]);
148laplaciImages[i-1]=createCompatibleDestImage(expandImage,null);
149intwidth=reduceImages[i-1].getWidth();
150intheight=reduceImages[i-1].getHeight();
151
152intewidth=expandImage.getWidth();
153width=(width>ewidth)?
ewidth:
width;
154height=(height>expandImage.getHeight())?
expandImage.getHeight():
height;
155System.out.println("width="+width+"expandwidth="+ewidth);
156
157int[]reducePixels=newint[width*height];
158int[]expandPixels=newint[width*height];
159int[]laPixels=newint[width*height];
160getRGB(reduceImages[i-1],0,0,width,height,reducePixels);
161getRGB(expandImage,0,0,width,height,expandPixels);
162intindex=0;
163inter=0,eg=0,eb=0;
164for(introw=0;row165intta=0,tr=0,tg=0,tb=0;
166for(intcol=0;col167index=row*width+col;
168ta=(reducePixels[index]>>24)&0xff;
169tr=(reducePixels[index]>>16)&0xff;
170tg=(reducePixels[index]>>8)&0xff;
171tb=reducePixels[index]&0xff;
172
173ta=(expandPixels[index]>>24)&0xff;
174er=(expandPixels[index]>>16)&0xff;
175eg=(expandPixels[index]>>8)&0xff;
176eb=expandPixels[index]&0xff;
177
178tr=tr-er;
179tg=tg-eg;
180tb=tb-eb;
181
182laPixels[index]=(ta<<24)|(clamp(tr)<<16)|(clamp(tg)<<8)|clamp(tb);
183}
184}
185setRGB(laplaciImages[i-1],0,0,width,height,laPixels);
186}
187
188returnlaplaciImages;
189}
190
191privateBufferedImagepyramidReduce(BufferedImagesrc){
192intwidth=src.getWidth();
193intheight=src.getHeight();
194BufferedImagedest=createSubCompatibleDestImage(src,null);
195int[]inPixels=newint[width*height];
196intow=width/2;
197intoh=height/2;
198int[]outPixels=newint[ow*oh];
199getRGB(src,0,0,width,height,inPixels);
200intinRow=0,inCol=0,index=0,oudex=0,ta=0;
201float[][]keneralData=this.getHVGaussianKeneral();
202for(introw=0;row203for(intcol=0;col204inRow=2*row;
205inCol=2*col;
206if(inRow>=height){
207inRow=0;
208}
209if(inCol>=width){
210inCol=0;
211}
212floatsumRed=0,sumGreen=0,sumBlue=0;
213for(intsubRow=-2;subRow<=2;subRow++){
214intinRowOff=inRow+subRow;
215if(inRowOff>=height||inRowOff<0){
216inRowOff=0;
217}
218for(intsubCol=-2;subCol<=2;subCol++){
219intinColOff=inCol+subCol;
220if(inColOff>=width||inColOff<0){
221inColOff=0;
222}
223index=inRowOff*width+inColOff;
224ta=(inPixels[index]>>24)&0xff;
225intred=(inPixels[index]>>16)&0xff;
226intgreen=(inPixels[index]>>8)&0xff;
227intblue=inPixels[index]&0xff;
228sumRed+=keneralData[subRow+2][subCol+2]*red;
229sumGreen+=keneralData[subRow+2][subCol+2]*green;
230sumBlue+=keneralData[subRow+2][subCol+2]*blue;
231}
232}
233
234oudex=row*ow+col;
235outPixels[oudex]=(ta<<24)|(clamp(sumRed)<<16)|(clamp(sumGreen)<<8)|clamp(sumBlue);
236}
237}
238setRGB(dest,0,0,ow,oh,outPixels);
239returndest;
240}
241
242publicBufferedImagecreateSubCompatibleDestImage(BufferedImagesrc,ColorModeldstCM){
243if(dstCM==null)
244dstCM=src.getColorModel();
245returnnewBufferedImage(dstCM,dstCM.createCompatibleWritableRaster(src.getWidth()/2,src.getHeight()/2),dstCM.isAlphaPremultiplied(),null);
246}
247
248publicBufferedImagecreateTwiceCompatibleDestImage(BufferedImagesrc,ColorModeldstCM){
249if(dstCM==null)
250dstCM=src.getColorModel();
251returnnewBufferedImage(dstCM,dstCM.createCompatibleWritableRaster(src.getWidth()*2,src.getHeight()*2),dstCM.isAlphaPremultiplied(),null);
252}
253
254publicBufferedImagepyramidExpand(BufferedImagesrc){
255intwidth=src.getWidth();
256intheight=src.getHeight();
257int[]inPixels=newint[width*height];
258getRGB(src,0,0,width,heigh