#pragma once #include #include // all opencv header #include #include "hdrplus/burst.h" #define TILE_SIZE 16 namespace hdrplus { class merge { public: int offset = TILE_SIZE / 2; float baseline_lambda_shot = 3.24 * pow( 10, -4 ); float baseline_lambda_read = 4.3 * pow( 10, -6 ); merge() = default; ~merge() = default; /** * @brief Run alignment on burst of images * * @param burst_images collection of burst images * @param alignments alignment in pixel value pair. * Outer most vector is per alternative image. * Inner most two vector is for horizontal & vertical tiles */ void process( hdrplus::burst& burst_images, \ std::vector>>>& alignments); /* std::vector get_other_tiles(); //return the other tile list T_1 to T_n std::vector vector_math(string operation, reference_tile, other_tile_list); //for loop allowing operations across single element and list std::vector scalar_vector_math(string operation, scalar num, std::vector tile_list); //for loop allowing operations across single element and list std::vector average_vector(std::vector tile_list); //take average of vector elements */ private: float tileRMS(cv::Mat tile) { cv::Mat squared; cv::multiply(tile, tile, squared); return sqrt(cv::mean(squared)[0]); } std::vector getNoiseVariance(std::vector tiles, float lambda_shot, float lambda_read) { std::vector noise_variance; for (auto tile : tiles) { noise_variance.push_back(lambda_shot * tileRMS(tile) + lambda_read); } return noise_variance; } cv::Mat cosineWindow1D(cv::Mat input, int window_size = TILE_SIZE) { cv::Mat output = input.clone(); for (int i = 0; i < input.cols; ++i) { output.at(0, i) = 1. / 2. - 1. / 2. * cos(2 * M_PI * (input.at(0, i) + 1 / 2.) / window_size); } return output; } cv::Mat cosineWindow2D(cv::Mat tile) { int window_size = tile.rows; // Assuming square tile cv::Mat output_tile = tile.clone(); cv::Mat window = cv::Mat::zeros(1, window_size, CV_32F); for(int i = 0; i < window_size; ++i) { window.at(i) = i; } cv::Mat window_x = cosineWindow1D(window, window_size); window_x = cv::repeat(window_x, window_size, 1); cv::Mat window_2d = window_x.mul(window_x.t()); cv::Mat window_applied; cv::multiply(tile, window_2d, window_applied, 1, CV_32F); return window_applied; } cv::Mat cat2Dtiles(std::vector> tiles) { std::vector rows; for (auto row_tiles : tiles) { cv::Mat row; cv::hconcat(row_tiles, row); rows.push_back(row); } cv::Mat img; cv::vconcat(rows, img); return img; } void circshift(cv::Mat &out, const cv::Point &delta) { cv::Size sz = out.size(); // error checking assert(sz.height > 0 && sz.width > 0); // no need to shift if ((sz.height == 1 && sz.width == 1) || (delta.x == 0 && delta.y == 0)) return; // delta transform int x = delta.x; int y = delta.y; if (x > 0) x = x % sz.width; if (y > 0) y = y % sz.height; if (x < 0) x = x % sz.width + sz.width; if (y < 0) y = y % sz.height + sz.height; // in case of multiple dimensions std::vector planes; split(out, planes); for (size_t i = 0; i < planes.size(); i++) { // vertical cv::Mat tmp0, tmp1, tmp2, tmp3; cv::Mat q0(planes[i], cv::Rect(0, 0, sz.width, sz.height - y)); cv::Mat q1(planes[i], cv::Rect(0, sz.height - y, sz.width, y)); q0.copyTo(tmp0); q1.copyTo(tmp1); tmp0.copyTo(planes[i](cv::Rect(0, y, sz.width, sz.height - y))); tmp1.copyTo(planes[i](cv::Rect(0, 0, sz.width, y))); // horizontal cv::Mat q2(planes[i], cv::Rect(0, 0, sz.width - x, sz.height)); cv::Mat q3(planes[i], cv::Rect(sz.width - x, 0, x, sz.height)); q2.copyTo(tmp2); q3.copyTo(tmp3); tmp2.copyTo(planes[i](cv::Rect(x, 0, sz.width - x, sz.height))); tmp3.copyTo(planes[i](cv::Rect(0, 0, x, sz.height))); } cv::merge(planes, out); } void fftshift(cv::Mat &out) { cv::Size sz = out.size(); cv::Point pt(0, 0); pt.x = (int) floor(sz.width / 2.0); pt.y = (int) floor(sz.height / 2.0); circshift(out, pt); } void ifftshift(cv::Mat &out) { cv::Size sz = out.size(); cv::Point pt(0, 0); pt.x = (int) ceil(sz.width / 2.0); pt.y = (int) ceil(sz.height / 2.0); circshift(out, pt); } std::vector getReferenceTiles(cv::Mat reference_image); cv::Mat mergeTiles(std::vector tiles, int rows, int cols); cv::Mat processChannel( hdrplus::burst& burst_images, \ std::vector>>>& alignments, \ cv::Mat channel_image, \ std::vector alternate_channel_i_list,\ float lambda_shot, \ float lambda_read); //temporal denoise std::vector temporal_denoise(std::vector reference_tiles, std::vector reference_tiles_DFT, std::vector noise_varaince); std::vector spatial_denoise(std::vector tiles, int num_alts, std::vector noise_variance, float spatial_factor); }; } // namespace hdrplus