opencv实现图片HDR功能

简介

  本篇主要是利用三张图片:过曝(相机设置exposure+1)、正常(相机设置exposure+0)、欠曝(相机设置exposure-1),来合成一张在亮出和暗处细节都清晰
的图片,来简易实现图片的HDR功能。

具体实现

实现代码

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
#include <string.h>
#include <opencv/cv.h>
#include <stdio.h>
#include "opencv2/photo/photo.hpp"
 
using namespace cv;
 
char highpicName[20];
char normalpicName[20];
char lowpicName[20];
Mat mat1, mat2, mat3, dst_mat, tmp_mat;
int highWidth, highHeight;
int normalWidth, normalHeight;
int lowWidth, lowHeight;
IplImage src1, src2, src3, dst_src, tmp_src;
double weight=0.5;
 
 
void hdrCale(Mat pic1, Mat pic2, Mat pic3){
	int i, j;
	CvScalar s1, s2, s3;
 
 
	src1 = pic1;
	src2 = pic2;
	src3 = pic3;
	dst_src = dst_mat;
	tmp_src = tmp_mat;
 
	cvCvtColor(&src2, &tmp_src, CV_BGR2GRAY);
	for(i=0; i< normalWidth; i++){
		for(j=0; j<normalHeight; j++){
			s1 = cvGet2D(&src1, i, j);
			s2 = cvGet2D(&tmp_src, i, j);
			s3 = cvGet2D(&src3, i, j);
			weight = 0.5 + (127 - s2.val[0]) * 0.002;
			s3.val[0] = (s1.val[0] * weight) + (s3.val[0] * (1-weight));
			s3.val[1] = (s1.val[1] * weight) + (s3.val[1] * (1-weight));
			s3.val[2] = (s1.val[2] * weight) + (s3.val[2] * (1-weight));
			cvSet2D(&dst_src, i, j, s3);
		}
	}
}
 
 
int main(int argc, char *argv[]){
	if(argc < 4){
		printf("Please input high exposure/normal exposure/low exposure picture!\n");
		return -1;
	}
	memcpy(highpicName, argv[1], sizeof(argv[1]));
	memcpy(normalpicName, argv[2], sizeof(argv[2]));
	memcpy(lowpicName, argv[3], sizeof(argv[3]));
	mat1 = imread(argv[1]);
	mat2 = imread(argv[2]);
	mat3 = imread(argv[3]);
	highWidth = mat1.rows;
	highHeight = mat1.cols;
	normalWidth = mat2.rows;
	normalHeight = mat2.cols;
	lowWidth = mat3.rows;
	lowHeight = mat3.cols;
	dst_mat = Mat(normalWidth, normalHeight, CV_8UC3, cv::Scalar(0, 0, 0));
	tmp_mat = Mat(normalWidth, normalHeight, CV_8UC1, cv::Scalar(0, 0, 0));
 
	hdrCale(mat1, mat2, mat3);
 
	imshow("normal", mat2);
	imshow("HDR", dst_mat);
	imwrite("HDR.jpg", dst_mat);
	cv::waitKey(0);
	return 0;
}

代码讲解

  1、首先进行相对应的初始化操作:运行软件时候,需要传入三张图片,顺序上分别是:过曝、正常、欠曝。打开这三张图片,保存在mat1、mat2、mat3
中,注意这三张图片必须大小一致。接着获取到图片的width和height。最后创建两张空白图片:tmp_mat和dst_mat。
        if(argc < 4){
		printf("Please input high exposure/normal exposure/low exposure picture!\n");
		return -1;
	}
	memcpy(highpicName, argv[1], sizeof(argv[1]));
	memcpy(normalpicName, argv[2], sizeof(argv[2]));
	memcpy(lowpicName, argv[3], sizeof(argv[3]));
	mat1 = imread(argv[1]);
	mat2 = imread(argv[2]);
	mat3 = imread(argv[3]);
	highWidth = mat1.rows;
	highHeight = mat1.cols;
	normalWidth = mat2.rows;
	normalHeight = mat2.cols;
	lowWidth = mat3.rows;
	lowHeight = mat3.cols;
	dst_mat = Mat(normalWidth, normalHeight, CV_8UC3, cv::Scalar(0, 0, 0));
	tmp_mat = Mat(normalWidth, normalHeight, CV_8UC1, cv::Scalar(0, 0, 0));
  2、接着进入到HDR的算法处理:对应的处理很简单,主要就是根据就是权重,把过曝和欠曝图片合成到dst_mat中。
具体做法:循环依次打开三张图片的同一位置像素,用正常曝光图片像素,利用公式:weight = 0.5 + (127 - s2.val[0]) * 0.002;
          来获得使用过曝、欠曝像素合成到dst_mat中对应使用的权值。接着:s3.val[0] = (s1.val[0] * weight) + (s3.val[0] * (1-weight));
          计算出合成像素值之后,写入到dst_mat对应的坐标位置。进而生成HDR照片。
void hdrCale(Mat pic1, Mat pic2, Mat pic3){
	int i, j;
	CvScalar s1, s2, s3;
 
	src1 = pic1;
	src2 = pic2;
	src3 = pic3;
	dst_src = dst_mat;
	tmp_src = tmp_mat;
 
	cvCvtColor(&src2, &tmp_src, CV_BGR2GRAY);
	for(i=0; i< normalWidth; i++){
		for(j=0; j<normalHeight; j++){
			s1 = cvGet2D(&src1, i, j);
			s2 = cvGet2D(&tmp_src, i, j);
			s3 = cvGet2D(&src3, i, j);
			weight = 0.5 + (127 - s2.val[0]) * 0.002;
			s3.val[0] = (s1.val[0] * weight) + (s3.val[0] * (1-weight));
			s3.val[1] = (s1.val[1] * weight) + (s3.val[1] * (1-weight));
			s3.val[2] = (s1.val[2] * weight) + (s3.val[2] * (1-weight));
			cvSet2D(&dst_src, i, j, s3);
		}
	}
}
  3、最后将正常照片和HDR照片显示初恋,并将hdr照片保存下来。
        imshow("normal", mat2);
	imshow("HDR", dst_mat);
	imwrite("HDR.jpg", dst_mat);
	cv::waitKey(0);

效果演示

 对应的效果演示如下:
    过曝图像:
        
    正常图像
        
    欠曝图像:
        
    HDR图像
        
时间: 2024-10-10 01:07:27

opencv实现图片HDR功能的相关文章

基于OpenCV的图片卡通化处理

学习OpenCV已有一段时间,除了研究各种算法的内容,在空闲之余,根据书本及资料的引导,尝试结合图像处理算法和日常生活联系起来,首先在台式机上(带摄像头)完成一系列视频流处理功能,开发平台为Qt5.3.2+OpenCV2.4.9. 本次试验实现的功能主要有: 调用摄像头捕获视频流: 将帧图像转换为素描效果图片: 将帧图像卡通化处理: 简单地生成"怪物"形象: 人脸肤色变换. 本节所有的算法均由类cartoon中的函数cartoonTransform()来实现: // Frame:输入每

java web中图片验证码功能实现

用户在注册网站信息的时候基本上都要数据验证码验证.那么图片验证码功能该如何实现呢? 大概步骤是: 1.在内存中创建缓存图片 2.设置背景色 3.画边框 4.写字母 5.绘制干扰信息 6.图片输出 废话不多说,直接上代码 package com.lsgjzhuwei.servlet.response; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.Buffer

php实现图片缩放功能类

http://www.poluoluo.com/jzxy/201312/255447.html <?php /** * Images类是一个图片处理类 * @package application.controllers * @since 1.0 */ class Images { /** * 缩放图片 * @param $source原图片 * @param $newfile新图片 * @param $pre缩放比例 */ public function thumn($source,$pre,

OpenCV -- 找图片轮廓

import cv2 img = cv2.imread( 'E:\A.jpeg' ) cv2.imshow( 'img', img ) gray = cv2.cvtColor( img, cv2.COLOR_BGR2GRAY ) ret, binary = cv2.threshold( gray, 127, 255, cv2.THRESH_BINARY ) contours, hierarchy = cv2.findContours( binary, cv2.RETR_TREE, cv2.CHA

html5仿小红书的图片标签功能

最近做了这样的一个功能,在wap网页上实现类似小红书app里的图片标签功能,很是蛋疼. 上传页示例如下图: 可以看到最上面的①是展示区域,也是编辑标签的操作区域:中间②是可滑动的缩略图,在此选择要编辑的图片:最下面③是"添加图片"和"添加标签"两个按钮. 废话不多说,下面介绍具体实现思路. 首先就是要有"选择图片"的按钮. 1 <input type="file" name="fileToUpload"

图片放大功能

图片放大功能插件及jquery.extend函数理解 前端时间,产品提出社区评论中的图片需要有放大功能.感觉可以共用,所以就想整合一个插件,过程中也借鉴了一些例子. 分析下自己的代码思路: var scaleImg = function(opts) { this.opts = $.extend({ wrap: '', clickimgs: '', callback: function(){} }, opts); this.images_n = []; //保存一条评论中的所有图片 this.$s

【微信公众平台开发】借用微信内置图片浏览功能

开发微信公众平台时,碰到文章中有很多图片,需要可以点开图片浏览:那么点击图片直接调用微信客户端自带的图片播放组件会省很多事.否则你得去摆弄折腾各种图片浏览插件,比如photoswipe. 个人封装功能成一个js文件.把该文件放到你需要的网页里面即可,这样文章当你点击图片时,就会调用图片浏览功能! <script> function addLoadEvent(func){ //将函数作为参数,此函数就是 onload 触发时需要执行的某个函数 var oldonload=window.onloa

UIScrollView控件实现图片缩放功能

UIScrollView控件实现图片缩放功能 iOS开发UI篇-UIScrollView控件实现图片缩放功能

php版给UEditor的图片在线管理栏目增加图片删除功能

1.找到uedior/dialogs/image/image.js文件,Add为修改部分的代码: /** * tab点击处理事件 * @param tabHeads * @param tabBodys * @param obj */ function clickHandler(tabHeads, tabBodys, obj) { //head样式更改 for (var k = 0, len = tabHeads.length; k < len; k++) { tabHeads[k].classN