diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index b15a4739a..1d85a87cb 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -94,12 +94,16 @@ CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21); -CV_EXPORTS_W void makeHDR(InputArrayOfArrays srcImgs, const std::vector& exp_times, OutputArray dst); +CV_EXPORTS_W void makeHDR(InputArrayOfArrays srcImgs, const std::vector& exp_times, OutputArray dst, bool align = false); CV_EXPORTS_W void tonemap(InputArray src, OutputArray dst, tonemap_algorithms algorithm, const std::vector& params = std::vector()); -CV_EXPORTS_W void exposureFusion(InputArrayOfArrays srcImgs, OutputArray dst, float wc = 1, float ws = 1, float we = 0); +CV_EXPORTS_W void exposureFusion(InputArrayOfArrays srcImgs, OutputArray dst, bool align = false, float wc = 1, float ws = 1, float we = 0); + +CV_EXPORTS_W void shiftMat(InputArray src, Point shift, OutputArray dst); + +CV_EXPORTS_W Point getExpShift(InputArray img0, InputArray img1, int max_bits = 6, int exclude_range = 4); } // cv #endif diff --git a/modules/photo/src/hdr_fusion.cpp b/modules/photo/src/hdr_fusion.cpp index 0d3e507be..5f2bf814d 100644 --- a/modules/photo/src/hdr_fusion.cpp +++ b/modules/photo/src/hdr_fusion.cpp @@ -85,7 +85,27 @@ static void checkImages(std::vector& images, bool hdr, const std::vector& _exp_times, OutputArray _dst) +static void alignImages(std::vector& src, std::vector& dst) +{ + dst.resize(src.size()); + + size_t pivot = src.size() / 2; + dst[pivot] = src[pivot]; + Mat gray_base; + cvtColor(src[pivot], gray_base, COLOR_RGB2GRAY); + + for(size_t i = 0; i < src.size(); i++) { + if(i == pivot) { + continue; + } + Mat gray; + cvtColor(src[i], gray, COLOR_RGB2GRAY); + Point shift = getExpShift(gray_base, gray); + shiftMat(src[i], shift, dst[i]); + } +} + +void makeHDR(InputArrayOfArrays _images, const std::vector& _exp_times, OutputArray _dst, bool align) { std::vector images; _images.getMatVector(images); @@ -93,6 +113,11 @@ void makeHDR(InputArrayOfArrays _images, const std::vector& _exp_times, O _dst.create(images[0].size(), CV_32FC3); Mat result = _dst.getMat(); + if(align) { + std::vector new_images; + alignImages(images, new_images); + images = new_images; + } std::vector exp_times(_exp_times.size()); for(size_t i = 0; i < exp_times.size(); i++) { exp_times[i] = log(_exp_times[i]); @@ -128,12 +153,17 @@ void makeHDR(InputArrayOfArrays _images, const std::vector& _exp_times, O result = result / max; } -void exposureFusion(InputArrayOfArrays _images, OutputArray _dst, float wc, float ws, float we) +void exposureFusion(InputArrayOfArrays _images, OutputArray _dst, bool align, float wc, float ws, float we) { std::vector images; _images.getMatVector(images); checkImages(images, false); + if(align) { + std::vector new_images; + alignImages(images, new_images); + images = new_images; + } std::vector weights(images.size()); Mat weight_sum = Mat::zeros(images[0].size(), CV_32FC1); for(size_t im = 0; im < images.size(); im++) { diff --git a/modules/photo/test/test_hdr.cpp b/modules/photo/test/test_hdr.cpp index b90e49167..5ea77ebf4 100644 --- a/modules/photo/test/test_hdr.cpp +++ b/modules/photo/test/test_hdr.cpp @@ -117,4 +117,27 @@ TEST(Photo_Tonemap, regression) minMaxLoc(abs(result - images[i]), NULL, &max); ASSERT_FALSE(max > 0); } +} + +TEST(Photo_Align, regression) +{ + const int TESTS_COUNT = 100; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "hdr/"; + + string file_name = folder + "grand_canal_1_45.jpg"; + Mat img = imread(file_name); + ASSERT_FALSE(img.empty()) << "Could not load input image " << file_name; + cvtColor(img, img, COLOR_RGB2GRAY); + + int max_bits = 6; + int max_shift = 64; + srand(time(0)); + + for(int i = 0; i < TESTS_COUNT; i++) { + Point shift(rand() % max_shift, rand() % max_shift); + Mat res; + shiftMat(img, shift, res); + Point calc = getExpShift(img, res, max_bits); + ASSERT_TRUE(calc == -shift); + } } \ No newline at end of file