|
|
|
@ -10,9 +10,12 @@ namespace hdrplus
|
|
|
|
|
void merge::process( hdrplus::burst& burst_images, \
|
|
|
|
|
std::vector<std::vector<std::vector<std::pair<int, int>>>>& alignments)
|
|
|
|
|
{
|
|
|
|
|
// 4.1 Noise Parameters and RMS
|
|
|
|
|
// Noise parameters calculated from baseline ISO noise parameters
|
|
|
|
|
double lambda_shot, lambda_read;
|
|
|
|
|
std::tie(lambda_shot, lambda_read) = burst_images.bayer_images[burst_images.reference_image_idx].get_noise_params();
|
|
|
|
|
|
|
|
|
|
// 4.2-4.4 Denoising and Merging
|
|
|
|
|
// Get padded bayer image
|
|
|
|
|
cv::Mat reference_image = burst_images.bayer_images_pad[burst_images.reference_image_idx];
|
|
|
|
|
// cv::imwrite("ref.jpg", reference_image);
|
|
|
|
@ -45,7 +48,7 @@ void merge::process( hdrplus::burst& burst_images, \
|
|
|
|
|
// cv::imwrite("ref" + std::to_string(i) + ".jpg", channel_i);
|
|
|
|
|
|
|
|
|
|
// Apply merging on the channel
|
|
|
|
|
cv::Mat merged_channel = processChannel(burst_images, alignments, channel_i);
|
|
|
|
|
cv::Mat merged_channel = processChannel(burst_images, alignments, channel_i, lambda_shot, lambda_read);
|
|
|
|
|
// cv::imwrite("merged" + std::to_string(i) + ".jpg", merged_channel);
|
|
|
|
|
|
|
|
|
|
// Put channel raw data back to channels
|
|
|
|
@ -150,14 +153,39 @@ cv::Mat merge::mergeTiles(std::vector<cv::Mat> tiles, int num_rows, int num_cols
|
|
|
|
|
|
|
|
|
|
cv::Mat merge::processChannel( hdrplus::burst& burst_images, \
|
|
|
|
|
std::vector<std::vector<std::vector<std::pair<int, int>>>>& alignments, \
|
|
|
|
|
cv::Mat channel_image) {
|
|
|
|
|
|
|
|
|
|
cv::Mat channel_image, \
|
|
|
|
|
float lambda_shot, \
|
|
|
|
|
float lambda_read) {
|
|
|
|
|
// Get tiles of the reference image
|
|
|
|
|
std::vector<cv::Mat> reference_tiles = getReferenceTiles(channel_image);
|
|
|
|
|
|
|
|
|
|
// TODO: Temporal Denoising
|
|
|
|
|
// Get noise variance (sigma**2 = lambda_shot * tileRMS + lambda_read)
|
|
|
|
|
std::vector<float> noise_variance = getNoiseVariance(reference_tiles, lambda_shot, lambda_read);
|
|
|
|
|
|
|
|
|
|
// Apply FFT on reference tiles (spatial to frequency)
|
|
|
|
|
std::vector<cv::Mat> reference_tiles_DFT;
|
|
|
|
|
for (auto ref_tile : reference_tiles) {
|
|
|
|
|
cv::Mat ref_tile_DFT;
|
|
|
|
|
ref_tile.convertTo(ref_tile_DFT, CV_32F);
|
|
|
|
|
cv::dft(ref_tile_DFT, ref_tile_DFT, cv::DFT_SCALE|cv::DFT_COMPLEX_OUTPUT);
|
|
|
|
|
reference_tiles_DFT.push_back(ref_tile_DFT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: 4.2 Temporal Denoising
|
|
|
|
|
|
|
|
|
|
// TODO: 4.3 Spatial Denoising
|
|
|
|
|
|
|
|
|
|
// TODO: Spatial Denoising
|
|
|
|
|
// Apply IFFT on reference tiles (frequency to spatial)
|
|
|
|
|
std::vector<cv::Mat> denoised_tiles;
|
|
|
|
|
for (auto dft_tile : reference_tiles_DFT) {
|
|
|
|
|
cv::Mat denoised_tile;
|
|
|
|
|
cv::dft(dft_tile, denoised_tile, cv::DFT_INVERSE|cv::DFT_REAL_OUTPUT);
|
|
|
|
|
denoised_tile.convertTo(denoised_tile, CV_16U);
|
|
|
|
|
denoised_tiles.push_back(denoised_tile);
|
|
|
|
|
}
|
|
|
|
|
reference_tiles = denoised_tiles;
|
|
|
|
|
|
|
|
|
|
// 4.4 Cosine Window Merging
|
|
|
|
|
// Process tiles through 2D cosine window
|
|
|
|
|
std::vector<cv::Mat> windowed_tiles;
|
|
|
|
|
for (auto tile : reference_tiles) {
|
|
|
|
|