好久之前,当我第一次看到这个算法时候,我就爱上它了,那个时候我
不懂什么是高
斯金字塔,但是我知道埃及有金字塔。一番研究之后,搞懂了什么是图
像金字塔于是
我写了一篇文章在我的博客上,可以看这里:
http://blog.csdn.net/jia20003/article/details/9116931
但是金字塔有什么应用呢,可能最广泛的一个应用就是实现图像融合和
图像的无缝
拼接于是我决定在研究一番,于是就有了这篇文章。好了不废话了。算
法需要三张
图片,两张图片是需要拼接的图片,最后一张是面罩图片,为什么需要
后面我会解释
面罩图片就是选取待拼接两张图片的目标边缘部分,多少合适根据需要。
Demo 演示
我是各占原图的 1/2 这样省事。
算法大致的步骤可以分为如下几步:
1.对两张待拼接的图片分别生成 DOG,关于什么是 DOG,怎么生成,
如果不知道
一定要看看这里:
2.对面罩图片(mask image)完成高斯金字塔,层数要跟 DOG 层数相同。
3. 根据面罩图片的权重,拼接两张图片的 DOG,生成一个 DOG 图片
4.用生成的 DOG 图片与 maskimage 金字塔 expand 生成的图片相加得
到每层,把每一次
叠加得到最后输出图片。
基于高斯金字塔图像融合的原理:
懂得高斯金字塔 DOG 的生成原理都明白,如果把金字塔 reduce 与
expand 的结果相减则
得到 DOG,而如果把 expand 结果与 DOG 结果相加则得到 reduce 处
理后的图像,因为
reduce 图像是间隔采样生成原图,而高斯金字塔融合正是巧妙的利用
了这点。
关键代码解释:
实现目标图像 DOG 提取代码如下,默认情况下是三层:
[java] view plaincopy
1. PyramidBlendProcessor pyramid = new PyramidBlendProcessor(image1, image2, ma
skImage);
2. BufferedImage[] image1Lapls = pyramid.getLaplacianPyramid(pyramid.pyramidDow
n(image1));
3. BufferedImage[] image2Lapls = pyramid.getLaplacianPyramid(pyramid.pyramidDow
n(image2));
4. BufferedImage[] maskPyramid = pyramid.pyramidDown(maskImage);
依靠 mask 权重实现两个目标图像 DOG 按层融合的代码如下:
[java] view plaincopy
1. public BufferedImage blendOneImage(BufferedImage image1, BufferedImage image
2, BufferedImage maskImage, BufferedImage blendedImage) {
2. int width = image1.getWidth();
3. int height = image1.getHeight();
4.
5. if ( blendedImage == null )
6. blendedImage = createCompatibleDestImage( maskImage, null );
7.
8. int[] image1Pixels = new int[width*height];
9. int[] image2Pixels = new int[width*height];
10. int[] maskPixels = new int[width*height];
11. int[] outPixels = new int[width*height];
12. getRGB( image1, 0, 0, width, height, image1Pixels );
13. getRGB( image2, 0, 0, width, height, image2Pixels );
14. getRGB( maskImage, 0, 0, width, height, maskPixels );
15. int index = 0;
16. float mr = 0, mg = 0, mb = 0;
17. for(int row=0; row<height; row++) {
18. int ta1 = 0, tr1 = 0, tg1 = 0, tb1 = 0;
19. int ta2 = 0, tr2 = 0, tg2 = 0, tb2 = 0;
20. int ta3 = 0, tr3 = 0, tg3 = 0, tb3 = 0;
21. for(int col=0; col<width; col++) {
22. index = row * width + col;
23. ta1 = (image1Pixels[index] >> 24) & 0xff;
24. tr1 = (image1Pixels[index] >> 16) & 0xff;
25. tg1 = (image1Pixels[index] >> 8) & 0xff;
26. tb1 = image1Pixels[index] & 0xff;
27.
28. ta2 = (image2Pixels[index] >> 24) & 0xff;
29. tr2 = (image2Pixels[index] >> 16) & 0xff;
30. tg2 = (image2Pixels[index] >> 8) & 0xff;
31. tb2 = image2Pixels[index] & 0xff;
32.
33. ta3 = (maskPixels[index] >> 24) & 0xff;
34. tr3 = (maskPixels[index] >> 16) & 0xff;
35. tg3 = (maskPixels[index] >> 8) & 0xff;
36. tb3 = maskPixels[index] & 0xff;
37.
38. mr = tr3 / 255.0f;
39. mg = tg3 / 255.0f;
40. mb = tb3 / 255.0f;
41. int br = (int)(mr * tr2 + (1.0f - mr) * tr1);
42. int bg = (int)(mg * tg2 + (1.0f - mr) * tg1);
43. int bb = (int)(mb * tb2 + (1.0f - mr) * tb1);
44. outPixels[index] = (ta1 << 24) | (clamp(br) << 16) | (clamp(b
g) << 8) | clamp(bb);
45. }
46. }
47. setRGB( blendedImage, 0, 0, width, height, outPixels );
48. return blendedImage;
49. }
合并 DOG 融合每层图片与 mask expand 之后的代码如下:
[java] view plaincopy
1. BufferedImage[] image1Lapls = this.pyramidUp(this.pyramidDown(maskImg));
2. BufferedImage result = null;
3. int size = blendResults.length;
4. for(int i=size - 1; i>=0; i--)
5. {
6. if((i-1) < 0){
7. result = this.collapse(image1Lapls[i], blendResults[i]);
8. } else {
9. image1Lapls[i-1] = this.pyramidExpand(this.collapse(image1Lapls[i],
blendResults[i]), image1Lapls[i-1].getWidth(), image1Lapls[i-1].getHeight());
10. }
11. }
12. // return image1Lapls[0];
13. return result;
图片一:
评论0