高动态范围图像HDR

        HDR(High Dynamic Range,高动态范围),由于目前无论是相机还是显示器,对图像亮度范围都限定在0~255之间,即256个亮度级别,但在自然界中,刺眼的阳光和微弱的星光,可能有成千上万倍的亮度差异。如果要在同一张照片上同时呈现两个亮度差异较大的物体,那么实际情况是,要么其中一个亮度过低,或者另一个过曝。根据不同应用场景,HDR有不同处理方式。

        其中一种方法为,采用不同曝光参数(ISO、快门速度)拍摄同一场景照片,对每张照片相同位置像素值求和,计算平均值,再将均值赋值给对应像素;另一种类似的处理方法为,相机采用较为平衡的曝光参数拍摄一张照片,根据这张照片分别按照亮度增强一定比例和亮度降低一定比例生成两张影像,将三张影像按照前面一种方法进行处理。

        当然在实际处理同一位置拍摄多张影像进行HDR时,需要考虑抖动等外界因素造成的图像错位,需要引入特征提取与匹配及裁剪影像。

        简单的demo实现代码:

public class Hdr {
	/**
	 * HDR实现 不同曝光参数的几张照片实现影像画质增强
	 * 
	 * @param images
	 * @return
	 */
	public BufferedImage hdrByImages(BufferedImage[] images) {
		int width = images[0].getWidth();
		int height = images[0].getHeight();
		BufferedImage resultImage = new BufferedImage(width, height, images[0].getType());
		int length = width * height;
		int pics = images.length;
		int[] tempR = new int[length];
		int[] tempG = new int[length];
		int[] tempB = new int[length];
		// 取出每张照片对应位置像素值
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				int index = i * height + j;
				for (int k = 0; k < pics; k++) {
					int rgb = images[k].getRGB(i, j);
					tempR[index] += (rgb >> 16) & 0xff;
					tempG[index] += (rgb >> 8) & 0xff;
					tempB[index] += rgb & 0xff;
				}
			}
		}
		// 求取均值,将均值作为最终结果输出
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				int index = i * height + j;
				int r = tempR[index] / pics;
				int g = tempG[index] / pics;
				int b = tempB[index] / pics;
				int rgb = (255 & 0xff) << 24 | (r & 0xff) << 16 | (g & 0xff) << 8 | (b & 0xff);
				resultImage.setRGB(i, j, rgb);
			}
		}
		return resultImage;
	}

	/**
	 * 用一张照片进行HDR计算
	 * 
	 * @param image
	 * @param lightParam
	 *            提高亮度参数
	 * @param darkParam
	 *            降低亮度参数
	 * @return
	 */
	public BufferedImage hdrByimage(BufferedImage image, double lightParam, double darkParam) {
		BufferedImage[] images = new BufferedImage[3];
		images[0] = image;
		images[1] = brightnessAdjustment(image, lightParam);
		images[2] = brightnessAdjustment(image, darkParam);
		BufferedImage result = hdrByImages(images);
		return result;
	}

	// 亮度调整
	public BufferedImage brightnessAdjustment(BufferedImage image, double param) {
		BufferedImage resultImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
		double R, G, B;
		for (int i = 0; i < image.getWidth(); i++) {
			for (int j = 0; j < image.getHeight(); j++) {
				int rgb = image.getRGB(i, j);
				R = (((rgb >> 16) & 0xff) * param);
				G = (((rgb >> 8) & 0xff) * param);
				B = ((rgb & 0xff) * param);

				rgb = ((255 & 0xff) << 24) | ((clamp((int) R) & 0xff) << 16) | ((clamp((int) G) & 0xff) << 8)
						| ((clamp((int) B) & 0xff));
				resultImage.setRGB(i, j, rgb);
			}
		}
		return resultImage;
	}

	private int clamp(int i) {
		if (i > 255) {
			return 255;
		}
		if (i < 0) {
			return 0;
		} else {
			return i;
		}

	}

	// 读取文件夹下多张影像
	public BufferedImage[] readImages(File input) throws Exception {
		String[] files = input.list();
		BufferedImage[] images = new BufferedImage[files.length];
		for (int i = 0; i < files.length; i++) {
			String in = files[i];
			File file = new File(input.toString() + "/" + in);
			images[i] = ImageIO.read(file);
		}
		return images;
	}

	//测试
	public static void main(String[] args) throws Exception {
		File input = new File("C:/Users/admin/Desktop/test/HDR");
		BufferedImage[] images = new Hdr().readImages(input);
		BufferedImage result = new Hdr().hdrByImages(images);
		File output = new File("C:/Users/admin/Desktop/test/HDR/result.jpg");
		ImageIO.write(result, "jpg", output);
	}
}

三张不同曝光参数的测试图像:

运行结果:

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TheMatrixs

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值