图像融合,把像素大小相同,拍摄位置相同的照片通过一定方式进行融合。下面介绍几种简单的图像融合方式。
1、通过对应像素均值进行融合。这种融合方式可用于处理亮度变换较大的图片,由于相机测光和成像水平有限,对于成像范围内阴暗部分和明亮部分往往处理不好,要保证阴暗部分,则会导致明亮部分过曝;要保证明亮部分成像,则会导致阴暗部分太暗。对于这种情况,一种是采用较低的曝光参数保证明亮部分不过曝,通过调整亮度显示出阴影部分,再通过均值合并生成图像。第二种方法是通过相机拍摄,相机采用三脚架固定位置,用不同曝光参数进行拍摄,拍摄完成后将几张影像进行均值合并。
另外,某些“鬼影”照片其实也是用类似方式合成的。
代码:
public BufferedImage imageCombineByAverage(List<BufferedImage> images) {
BufferedImage tempImage = new BufferedImage(images.get(0).getWidth(), images.get(0).getHeight(), images.get(0).getType());
for(int i = 0; i < images.get(0).getWidth(); i++) {
for(int j = 0; j < images.get(0).getHeight(); j++) {
int R = 0,G = 0,B = 0;
for(BufferedImage image : images) {
int rgb = image.getRGB(i, j);
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = rgb & 0xff;
R += r;
G += g;
B += b;
}
int aveR = R / images.size();
int aveG = G / images.size();
int aveB = B / images.size();
int RGB = (255 & 0xff) << 24 | (clamp(aveR) & 0xff) << 16 | (clamp(aveG) & 0xff) << 8 | clamp(aveB) & 0xff;
tempImage.setRGB(i, j, RGB);
}
}
return tempImage;
}
2、通过对应像素值求和。适用于亮度很暗的场景,由于在亮度很低的场景下,采用高ISO可能会产生很多噪点,可以通过较低的曝光参数,固定相机位置,采用多次拍摄,对多张照片进行对应位置像素值求和的方式提高亮度和画质。
另外也可以用于对影像进行特征提取或边缘提取后,将处理后的特征点、线图像与原图进行合并。
public BufferedImage imageCombineByAddAll(List<BufferedImage> images) {
BufferedImage tempImage = new BufferedImage(images.get(0).getWidth(), images.get(0).getHeight(), images.get(0).getType());
for(int i = 0; i < images.get(0).getWidth(); i++) {
for(int j = 0; j < images.get(0).getHeight(); j++) {
int R = 0,G = 0,B = 0;
for(BufferedImage image : images) {
int rgb = image.getRGB(i, j);
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = rgb & 0xff;
R += r;
G += g;
B += b;
}
int RGB = (255 & 0xff) << 24 | (clamp(R) & 0xff) << 16 | (clamp(G) & 0xff) << 8 | clamp(B) & 0xff;
tempImage.setRGB(i, j, RGB);
}
}
return tempImage;
}
3、最低值合并。
public BufferedImage imageCombineByMin(List<BufferedImage> images) {
BufferedImage tempImage = new BufferedImage(images.get(0).getWidth(), images.get(0).getHeight(), images.get(0).getType());
for(int i = 0; i < images.get(0).getWidth(); i++) {
for(int j = 0; j < images.get(0).getHeight(); j++) {
List<Integer> rList = new ArrayList<>();
List<Integer> gList = new ArrayList<>();
List<Integer> bList = new ArrayList<>();
for(BufferedImage image : images) {
int rgb = image.getRGB(i, j);
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = rgb & 0xff;
rList.add(r);
gList.add(g);
bList.add(b);
}
Collections.sort(rList);
Collections.sort(gList);
Collections.sort(bList);
int minR = rList.get(0);
int minG = gList.get(0);
int minB = bList.get(0);
int RGB = (255 & 0xff) << 24 | (clamp(minR) & 0xff) << 16 | (clamp(minG) & 0xff) << 8 | clamp(minB) & 0xff;
tempImage.setRGB(i, j, RGB);
}
}
return tempImage;
}