Created
April 11, 2014 13:38
-
-
Save soravux/10469733 to your computer and use it in GitHub Desktop.
HDR using OpenCV with libexif
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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