add align

main
Xiao Song 3 years ago
parent fac1b87b44
commit e473ed5ebd

@ -84,3 +84,9 @@ target_link_libraries( test_utility
add_executable( test_burst tests/test_burst.cpp ) add_executable( test_burst tests/test_burst.cpp )
target_link_libraries( test_burst target_link_libraries( test_burst
${PROJECT_NAME} ) ${PROJECT_NAME} )
add_executable( test_align tests/test_align.cpp ${src_files} )
target_link_libraries( test_align
${OpenCV_LIBS}
${LIBRAW_LIBRARY}
exiv2lib )

@ -8,7 +8,7 @@
2. LibRaw 2. LibRaw
1. MacOS : `brew install libraw libpng libjpeg` 1. MacOS : `brew install libraw libpng libjpeg`
2. Ubuntu : 2. Ubuntu : `sudo apt install libraw-dev`
step 1: download libraw package here: https://www.libraw.org/download step 1: download libraw package here: https://www.libraw.org/download

@ -34,4 +34,17 @@ class align
const int num_levels = 4; const int num_levels = 4;
}; };
void align_image_level( \
const cv::Mat& ref_img, \
const cv::Mat& alt_img, \
const std::vector<std::vector<std::pair<int, int>>>& reftiles_start, \
std::vector<std::vector<std::pair<int, int>>>& prev_aligement, \
std::vector<std::vector<std::pair<int, int>>>& alignment, \
int scale_factor_prev_curr, \
int tile_size, \
int prev_tile_size, \
int search_radiou, \
int distance );
} // namespace hdrplus } // namespace hdrplus

@ -76,10 +76,10 @@ cv::Mat box_filter_kxk( cv::Mat src_image )
{ {
T box_sum = T(0); T box_sum = T(0);
#pragma LOOP_UNROLL //#pragma LOOP_UNROLL
for ( int kernel_row_i = 0; kernel_row_i < kernel; ++kernel_row_i ) for ( int kernel_row_i = 0; kernel_row_i < kernel; ++kernel_row_i )
{ {
#pragma LOOP_UNROLL //#pragma LOOP_UNROLL
for ( int kernel_col_i = 0; kernel_col_i < kernel; ++kernel_col_i ) for ( int kernel_col_i = 0; kernel_col_i < kernel; ++kernel_col_i )
{ {
box_sum += src_image_ptr[ ( row_i + kernel_row_i ) * src_step + ( col_i + kernel_col_i ) ]; box_sum += src_image_ptr[ ( row_i + kernel_row_i ) * src_step + ( col_i + kernel_col_i ) ];

@ -1,6 +1,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <limits> #include <limits>
#include <cstdio>
#include <stdexcept> // std::runtime_error #include <stdexcept> // std::runtime_error
#include <opencv2/opencv.hpp> // all opencv header #include <opencv2/opencv.hpp> // all opencv header
#include "hdrplus/align.h" #include "hdrplus/align.h"
@ -74,8 +75,8 @@ static void upsample_alignment_stride( \
{ {
// Scale alignment // Scale alignment
std::pair<int, int> align_i = src_alignment[ row_i ][ col_i ]; std::pair<int, int> align_i = src_alignment[ row_i ][ col_i ];
align_i.first *= scale_factor; align_i.first *= stride;
align_i.second *= scale_factor; align_i.second *= stride;
// repeat // repeat
for ( int stride_row_i = 0; stride_row_i < stride; ++stride_row_i ) for ( int stride_row_i = 0; stride_row_i < stride; ++stride_row_i )
@ -89,8 +90,27 @@ static void upsample_alignment_stride( \
} }
} }
template <typename T>
void print_tile( const cv::Mat& img, int tile_size, int start_idx_x, int start_idx_y )
{
const T* img_ptr = (T*)img.data;
int src_height = img.size().height;
int src_width = img.size().width;
int src_step = img.step1();
for ( int row = 0; row < tile_size; ++row )
{
const T* img_ptr_row = img_ptr + row * src_step;
for ( int col = 0; col < tile_size; ++col )
{
printf("%d ", img_ptr_row[ col ] );
}
printf("\n");
}
printf("\n");
}
static void align_image_level( \ void align_image_level( \
const cv::Mat& ref_img, \ const cv::Mat& ref_img, \
const cv::Mat& alt_img, \ const cv::Mat& alt_img, \
const std::vector<std::vector<std::pair<int, int>>>& reftiles_start, \ const std::vector<std::vector<std::pair<int, int>>>& reftiles_start, \
@ -113,6 +133,8 @@ static void align_image_level( \
int num_tiles_h = reftiles_start.size(); int num_tiles_h = reftiles_start.size();
int num_tiles_w = reftiles_start.at( 0 ).size(); int num_tiles_w = reftiles_start.at( 0 ).size();
printf("num tile h %d, num tile w %d\n", num_tiles_h, num_tiles_w);
/* Upsample pervious layer alignment */ /* Upsample pervious layer alignment */
std::vector<std::vector<std::pair<int, int>>> upsampled_prev_aligement; std::vector<std::vector<std::pair<int, int>>> upsampled_prev_aligement;
@ -132,6 +154,7 @@ static void align_image_level( \
} }
else if ( scale_factor_prev_curr == 4 ) else if ( scale_factor_prev_curr == 4 )
{ {
// TODO: add choose from 3 neighbour
upsample_alignment_stride<4>( prev_aligement, upsampled_prev_aligement ); upsample_alignment_stride<4>( prev_aligement, upsampled_prev_aligement );
} }
else else
@ -145,19 +168,26 @@ static void align_image_level( \
cv::copyMakeBorder( alt_img, \ cv::copyMakeBorder( alt_img, \
alt_img_pad, \ alt_img_pad, \
search_radiou, search_radiou, search_radiou, search_radiou, \ search_radiou, search_radiou, search_radiou, search_radiou, \
cv::BORDER_CONSTANT, std::numeric_limits<char16_t>::max ); cv::BORDER_CONSTANT, cv::Scalar( UINT_LEAST16_MAX ) );
/* Iterate through all reference tile & compute distance */ /* Iterate through all reference tile & compute distance */
for ( int ref_tile_row = 0; ref_tile_row < num_tile_h; ref_tile_row++ ) for ( int ref_tile_row = 0; ref_tile_row < num_tiles_h; ref_tile_row++ )
{ {
for ( int ref_tile_col = 0; ref_tile_col < num_tile_w; ref_tile_col++ ) for ( int ref_tile_col = 0; ref_tile_col < num_tiles_w; ref_tile_col++ )
{ {
// Upper left index of reference tile // Upper left index of reference tile
int ref_tile_idx_x = reftiles_start.at( ref_tile_row ).at( ref_tile_col ); int ref_tile_idx_x = reftiles_start.at( ref_tile_row ).at( ref_tile_col ).first;
int ref_tile_idx_y = reftiles_start.at( ref_tile_row ).at( ref_tile_col ); int ref_tile_idx_y = reftiles_start.at( ref_tile_row ).at( ref_tile_col ).second;
// Upsampled alignment at this tile // Upsampled alignment at this tile
int // int prev_alignment_x = upsampled_prev_aligement.at( ref_tile_row ).at( ref_tile_col ).first;
// int prev_alignment_y = upsampled_prev_aligement.at( ref_tile_row ).at( ref_tile_col ).second;
// int alt_tile_idx_x = ref_tile_idx_x + prev_alignment_x;
// int alt_tile_idx_y = ref_tile_idx_y + prev_alignment_y;
printf("Ref img tile [%d, %d]\n", ref_tile_row, ref_tile_col );
print_tile<uint16_t>( ref_img, 8, ref_tile_idx_x, ref_tile_idx_y );
} }
} }
@ -169,13 +199,13 @@ static void build_per_pyramid_reftiles_start( \
const std::vector<std::vector<cv::Mat>>& per_grayimg_pyramid, \ const std::vector<std::vector<cv::Mat>>& per_grayimg_pyramid, \
const std::vector<int>& grayimg_tile_sizes ) const std::vector<int>& grayimg_tile_sizes )
{ {
per_pyramid_reftiles_start.resize( per_grayimg_pyramid.size() ); per_pyramid_reftiles_start.resize( per_grayimg_pyramid.at(0).size() );
// Every image pyramid level // Every image pyramid level
for ( int level_i = 0; level_i < per_grayimg_pyramid.size(); level_i++ ) for ( int level_i = 0; level_i < per_grayimg_pyramid.at(0).size(); level_i++ )
{ {
int level_i_img_h = per_grayimg_pyramid.at( level_i ).size().height; int level_i_img_h = per_grayimg_pyramid.at(0).at( level_i ).size().height;
int level_i_img_w = per_grayimg_pyramid.at( level_i ).size().width; int level_i_img_w = per_grayimg_pyramid.at(0).at( level_i ).size().width;
int level_i_tile_size = grayimg_tile_sizes.at( level_i ); int level_i_tile_size = grayimg_tile_sizes.at( level_i );
@ -190,7 +220,7 @@ static void build_per_pyramid_reftiles_start( \
for ( int tile_row_j = 0; tile_row_j < num_tiles_w; tile_row_j++ ) for ( int tile_row_j = 0; tile_row_j < num_tiles_w; tile_row_j++ )
{ {
per_pyramid_reftiles_start.at( level_i ).at( tile_col_i ).at( tile_row_j ) \ per_pyramid_reftiles_start.at( level_i ).at( tile_col_i ).at( tile_row_j ) \
= std::make_pair<int, int>( tile_col_i * level_i_tile_size, tile_col_j * level_i_tile_size ); = std::make_pair<int, int>( tile_col_i * level_i_tile_size, tile_row_j * level_i_tile_size );
} }
} }
} }
@ -223,7 +253,6 @@ void align::process( const hdrplus::burst& burst_images, \
printf("\n"); printf("\n");
#endif #endif
// Tile starting location for each tile level // Tile starting location for each tile level
std::vector<std::vector<std::vector<std::pair<int, int>>>> per_pyramid_reftiles_start; std::vector<std::vector<std::vector<std::pair<int, int>>>> per_pyramid_reftiles_start;
@ -245,25 +274,27 @@ void align::process( const hdrplus::burst& burst_images, \
// Align every level from coarse to grain // Align every level from coarse to grain
// level 0 : finest level, the original image // level 0 : finest level, the original image
// level 3 : coarsest level // level 3 : coarsest level
std::vector<std::pair<int, int>> curr_alignment; std::vector<std::vector<std::pair<int, int>>> curr_alignment;
std::vector<std::pair<int, int>> prev_alignment; std::vector<std::vector<std::pair<int, int>>> prev_alignment;
for ( int level_i = num_levels - 1; level_i >= 0; level_i-- ) for ( int level_i = num_levels - 1; level_i >= 0; level_i-- )
{ {
align_image_level( align_image_level(
ref_grayimg_pyramid[ level_i ], // reference image at current level ref_grayimg_pyramid[ level_i ], // reference image at current level
alt_grayimg_pyramid[ level_i ], // alternative image at current level alt_grayimg_pyramid[ level_i ], // alternative image at current level
per_pyramid_reftiles_start[ level_i ] // reference tile start location for current level per_pyramid_reftiles_start[ level_i ], // reference tile start location for current level
prev_alignment, // previous layer alignment prev_alignment, // previous layer alignment
curr_alignment, // current layer alignment curr_alignment, // current layer alignment
( level_i == ( num_levels - 1 ) ? -1 : inv_scale_factors[ level_i ] ), // scale factor between previous layer and current layer. -1 if current layer is the coarsest layer ( level_i == ( num_levels - 1 ) ? -1 : inv_scale_factors[ level_i ] ), // scale factor between previous layer and current layer. -1 if current layer is the coarsest layer
grayimg_tile_sizes[ level_i ], // current level tile size grayimg_tile_sizes[ level_i ], // current level tile size
( level_i == ( num_levels - 1 ) ? -1 : tile_sizes[ level_i + 1 ] ), // previous level tile size ( level_i == ( num_levels - 1 ) ? -1 : grayimg_tile_sizes[ level_i + 1 ] ), // previous level tile size
grayimg_search_radious[ level_i ], // search radious grayimg_search_radious[ level_i ], // search radious
distances[ level_i ] ); // L1/L2 distance distances[ level_i ] ); // L1/L2 distance
// make curr alignment as previous alignment // make curr alignment as previous alignment
prev_alignment.swap( curr_alignment ); prev_alignment.swap( curr_alignment );
curr_alignment.clear(); curr_alignment.clear();
break;
} // for pyramid level } // for pyramid level

@ -78,7 +78,7 @@ std::pair<double, double> bayer_image::get_noise_params() const
double lambda_read_p = (iso_ / 100.0f) * (iso_ / 100.0f) * baseline_lambda_read; double lambda_read_p = (iso_ / 100.0f) * (iso_ / 100.0f) * baseline_lambda_read;
double black_level = (black_level_per_channel[0] + \ double black_level = (black_level_per_channel[0] + \
black_level_per_channel[1] + \ black_level_per_channel[1] + \
black_level_per_channel[2] + \ black_level_per_channel[2] + \
black_level_per_channel[3]) / 4.0; black_level_per_channel[3]) / 4.0;

@ -0,0 +1,24 @@
#include "hdrplus/align.h"
#include "hdrplus/bayer_image.h"
#include "hdrplus/burst.h"
#include <cstdio>
void test_align_one_level(int argc, char** argv)
{
if ( argc != 3 )
{
printf("Usage ./test_align BUTST_PATH REF_PATH");
}
hdrplus::burst burst_images( argv[1], argv[2] );
std::vector<std::vector<std::vector<std::pair<int, int>>>> alignments;
hdrplus::align align_module;
align_module.process( burst_images, alignments );
}
int main(int argc, char** argv)
{
test_align_one_level(argc, argv);
}
Loading…
Cancel
Save