Skip to content

Instantly share code, notes, and snippets.

@soravux
Created April 11, 2014 13:38
Show Gist options
  • Select an option

  • Save soravux/10469733 to your computer and use it in GitHub Desktop.

Select an option

Save soravux/10469733 to your computer and use it in GitHub Desktop.
HDR using OpenCV with libexif
#include <libexif/exif-data.h>
#include <opencv2/photo.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <iostream>
#include <fstream>
#include <dirent.h>
using namespace cv;
using namespace std;
void loadExposureSeq(string, vector<Mat>&, vector<float>&);
int main(int, char**argv)
{
vector<Mat> images;
vector<float> times;
loadExposureSeq(argv[1], images, times);
Mat response;
Ptr<CalibrateDebevec> calibrate = createCalibrateDebevec();
calibrate->process(images, response, times);
Mat hdr;
Ptr<MergeDebevec> merge_debevec = createMergeDebevec();
merge_debevec->process(images, hdr, times, response);
Mat ldr;
Ptr<TonemapDurand> tonemap = createTonemapDurand(2.2f);
tonemap->process(hdr, ldr);
Mat fusion;
Ptr<MergeMertens> merge_mertens = createMergeMertens();
merge_mertens->process(images, fusion);
imwrite("fusion.png", fusion * 255);
imwrite("ldr.png", ldr * 255);
imwrite("hdr.hdr", hdr);
return 0;
}
/* Remove spaces on the right of the string */
static void trim_spaces(char *buf)
{
char *s = buf-1;
for (; *buf; ++buf) {
if (*buf != ' ') {
s = buf;
}
}
*++s = 0; /* nul terminate the string on the first of the final spaces */
}
string exifGetTag(ExifData *d, ExifIfd ifd, ExifTag tag)
{
/* See if this tag exists */
ExifEntry *entry = exif_content_get_entry(d->ifd[ifd], tag);
if (entry) {
char buf[1024];
/* Get the contents of the tag in human-readable form */
exif_entry_get_value(entry, buf, sizeof(buf));
/* Don't bother printing it if it's entirely blank */
trim_spaces(buf);
if (*buf) {
//printf("%s: %s\n", exif_tag_get_name_in_ifd(tag,ifd), buf);
return string(buf);
}
}
return string("");
}
float exifGetExposure(ExifData *d)
{
string data = exifGetTag(d, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME);
float retVal = -1.0f;
/* Check if there is a division
* atoi() will skip any non-numeric character (the "s") */
size_t slash_pos = data.find("/");
if (slash_pos != string::npos) {
retVal = 1.0f / (float)atoi(&(data.c_str()[slash_pos + 1]));
} else {
retVal = (float)atoi(data.c_str());
}
printf("Found exposure time: %f\n", retVal);
return retVal;
}
vector<string> getFilesInFolder(string in_folder)
{
struct dirent *entry;
DIR *dp;
vector<string> results;
dp = opendir(in_folder.c_str());
if (dp == NULL) {
fprintf(stderr, "Could not list files of directory %s\n", in_folder.c_str());
return results;
}
while ((entry = readdir(dp))) {
// Skip . and .. and hidden files
if (entry->d_name[0] != '.') {
results.push_back(entry->d_name);
}
}
closedir(dp);
return results;
}
void loadExposureSeq(string path, vector<Mat>& images, vector<float>& times)
{
vector<string> filenames = getFilesInFolder(path);
vector<string>::iterator filenames_it;
ExifData *ed;
for (filenames_it = filenames.begin(); filenames_it != filenames.end(); ++filenames_it) {
string fullpath = path + string("/") + *filenames_it;
printf("Reading %s...\n", fullpath.c_str());
// Get exposure from EXIF data
ed = exif_data_new_from_file(fullpath.c_str());
if (!ed) {
fprintf(stderr, "File not readable or no EXIF data in file %s\n", fullpath.c_str());
continue;
}
times.push_back(exifGetExposure(ed));
// Get image
Mat img = imread(fullpath);
images.push_back(img);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment