zoukankan      html  css  js  c++  java
  • OpenCV 实现图片HDR功能

    简介

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

    具体实现

    实现代码

     1 #include <opencv2/core/core.hpp>                                                                                                     
     2 #include <opencv2/highgui/highgui.hpp>
     3 #include <math.h>
     4 #include <string.h>
     5 #include <opencv/cv.h>
     6 #include <stdio.h>
     7 #include "opencv2/photo/photo.hpp"
     8  
     9 using namespace cv;
    10  
    11 char highpicName[20];
    12 char normalpicName[20];
    13 char lowpicName[20];
    14 Mat mat1, mat2, mat3, dst_mat, tmp_mat;
    15 int highWidth, highHeight;
    16 int normalWidth, normalHeight;
    17 int lowWidth, lowHeight;
    18 IplImage src1, src2, src3, dst_src, tmp_src;
    19 double weight=0.5;
    20  
    21  
    22 void hdrCale(Mat pic1, Mat pic2, Mat pic3){
    23     int i, j;
    24     CvScalar s1, s2, s3;
    25  
    26  
    27     src1 = pic1;
    28     src2 = pic2;
    29     src3 = pic3;
    30     dst_src = dst_mat;
    31     tmp_src = tmp_mat;
    32  
    33     cvCvtColor(&src2, &tmp_src, CV_BGR2GRAY);
    34     for(i=0; i< normalWidth; i++){
    35         for(j=0; j<normalHeight; j++){
    36             s1 = cvGet2D(&src1, i, j);
    37             s2 = cvGet2D(&tmp_src, i, j);
    38             s3 = cvGet2D(&src3, i, j);
    39             weight = 0.5 + (127 - s2.val[0]) * 0.002;
    40             s3.val[0] = (s1.val[0] * weight) + (s3.val[0] * (1-weight));
    41             s3.val[1] = (s1.val[1] * weight) + (s3.val[1] * (1-weight));
    42             s3.val[2] = (s1.val[2] * weight) + (s3.val[2] * (1-weight));
    43             cvSet2D(&dst_src, i, j, s3);
    44         }    
    45     }
    46 }
    47  
    48  
    49 int main(int argc, char *argv[]){
    50     if(argc < 4){
    51         printf("Please input high exposure/normal exposure/low exposure picture!
    ");
    52         return -1;    
    53     }
    54     memcpy(highpicName, argv[1], sizeof(argv[1]));
    55     memcpy(normalpicName, argv[2], sizeof(argv[2]));
    56     memcpy(lowpicName, argv[3], sizeof(argv[3]));
    57     mat1 = imread(argv[1]);
    58     mat2 = imread(argv[2]);
    59     mat3 = imread(argv[3]);
    60     highWidth = mat1.rows;
    61     highHeight = mat1.cols;
    62     normalWidth = mat2.rows;
    63     normalHeight = mat2.cols;
    64     lowWidth = mat3.rows;
    65     lowHeight = mat3.cols;
    66     dst_mat = Mat(normalWidth, normalHeight, CV_8UC3, cv::Scalar(0, 0, 0));
    67     tmp_mat = Mat(normalWidth, normalHeight, CV_8UC1, cv::Scalar(0, 0, 0));
    68  
    69     hdrCale(mat1, mat2, mat3);
    70  
    71     imshow("normal", mat2);
    72     imshow("HDR", dst_mat);
    73     imwrite("HDR.jpg", dst_mat);
    74     cv::waitKey(0);
    75     return 0;
    76 }

    代码讲解
      1、首先进行相对应的初始化操作:运行软件时候,需要传入三张图片,顺序上分别是:过曝、正常、欠曝。打开这三张图片,保存在mat1、mat2、mat3
    中,注意这三张图片必须大小一致。接着获取到图片的width和height。最后创建两张空白图片:tmp_mat和dst_mat。

     1         if(argc < 4){
     2         printf("Please input high exposure/normal exposure/low exposure picture!
    ");
     3         return -1;    
     4     }
     5     memcpy(highpicName, argv[1], sizeof(argv[1]));
     6     memcpy(normalpicName, argv[2], sizeof(argv[2]));
     7     memcpy(lowpicName, argv[3], sizeof(argv[3]));
     8     mat1 = imread(argv[1]);
     9     mat2 = imread(argv[2]);
    10     mat3 = imread(argv[3]);
    11     highWidth = mat1.rows;
    12     highHeight = mat1.cols;
    13     normalWidth = mat2.rows;
    14     normalHeight = mat2.cols;
    15     lowWidth = mat3.rows;
    16     lowHeight = mat3.cols;
    17     dst_mat = Mat(normalWidth, normalHeight, CV_8UC3, cv::Scalar(0, 0, 0));
    18     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照片。

     1 void hdrCale(Mat pic1, Mat pic2, Mat pic3){
     2     int i, j;
     3     CvScalar s1, s2, s3;
     4  
     5     src1 = pic1;
     6     src2 = pic2;
     7     src3 = pic3;
     8     dst_src = dst_mat;
     9     tmp_src = tmp_mat;
    10  
    11     cvCvtColor(&src2, &tmp_src, CV_BGR2GRAY);
    12     for(i=0; i< normalWidth; i++){
    13         for(j=0; j<normalHeight; j++){
    14             s1 = cvGet2D(&src1, i, j);
    15             s2 = cvGet2D(&tmp_src, i, j);
    16             s3 = cvGet2D(&src3, i, j);
    17             weight = 0.5 + (127 - s2.val[0]) * 0.002;
    18             s3.val[0] = (s1.val[0] * weight) + (s3.val[0] * (1-weight));
    19             s3.val[1] = (s1.val[1] * weight) + (s3.val[1] * (1-weight));
    20             s3.val[2] = (s1.val[2] * weight) + (s3.val[2] * (1-weight));
    21             cvSet2D(&dst_src, i, j, s3);
    22         }    
    23     }
    24 }
     3、最后将正常照片和HDR照片显示初恋,并将hdr照片保存下来。
    1     imshow("normal", mat2);
    2     imshow("HDR", dst_mat);
    3     imwrite("HDR.jpg", dst_mat);
    4     cv::waitKey(0);

    效果演示

     对应的效果演示如下:
        过曝图像:

    正常图像

    欠曝图像:

    HDR图像

  • 相关阅读:
    程序员学习提高必看的一篇文章
    SpringAOP拦截器的代理机制
    springboot03_RabbitMQ
    Docker_02
    Docker_01
    Redis_02
    Redis_01
    关于Linux下内存和Swap
    密码学DAY2
    密码学DAY1_02
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/15189357.html
Copyright © 2011-2022 走看看