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图像
文章来自:http://blog.csdn.net/u011630458/article/details/46592013