diff --git a/src/align.cpp b/src/align.cpp index c9798cb..f1a5aee 100644 --- a/src/align.cpp +++ b/src/align.cpp @@ -65,16 +65,21 @@ static void build_per_grayimg_pyramid( \ } -template< int stride > -static void upsample_alignment_stride( \ +template< int pyramid_scale_factor_prev_curr, int tilesize_scale_factor_prev_curr > +static void build_upsampled_prev_aligement( \ std::vector>>& src_alignment, \ std::vector>>& dst_alignment ) { + printf("build_upsampled_prev_aligement with scale factor %d and tile size factor %d\n", \ + pyramid_scale_factor_prev_curr, tilesize_scale_factor_prev_curr ); + int src_height = src_alignment.size(); int src_width = src_alignment[ 0 ].size(); - int dst_height = src_height * stride; - int dst_width = src_width * stride; + int repeat_factor = pyramid_scale_factor_prev_curr / tilesize_scale_factor_prev_curr; + + int dst_height = src_height * repeat_factor; + int dst_width = src_width * repeat_factor; // Allocate data for dst_alignment dst_alignment.resize( dst_height, std::vector>( dst_width ) ); @@ -86,15 +91,15 @@ static void upsample_alignment_stride( \ { // Scale alignment std::pair align_i = src_alignment[ row_i ][ col_i ]; - align_i.first *= stride; - align_i.second *= stride; + align_i.first *= pyramid_scale_factor_prev_curr; + align_i.second *= pyramid_scale_factor_prev_curr; // repeat - for ( int stride_row_i = 0; stride_row_i < stride; ++stride_row_i ) + for ( int repeat_row_i = 0; repeat_row_i < repeat_factor; ++repeat_row_i ) { - for ( int stride_col_i = 0; stride_col_i < stride; ++stride_col_i ) + for ( int repeat_col_i = 0; repeat_col_i < repeat_factor; ++repeat_col_i ) { - dst_alignment[ row_i + stride_row_i ][ col_i + stride_col_i ] = align_i; + dst_alignment[ row_i + repeat_row_i ][ col_i + repeat_col_i ] = align_i; } } } @@ -292,10 +297,6 @@ void align_image_level( \ int search_radiou, \ int distance_type ) { - /* Basic infos */ - int num_tiles_h = ref_img.size().height / (curr_tile_size / 2) - 1; - int num_tiles_w = ref_img.size().width / (curr_tile_size / 2 ) - 1 ; - // Every align image level share the same distance function. // Use function ptr to reduce if else overhead inside for loop unsigned long long (*distance_func_ptr)(const cv::Mat&, const cv::Mat&, int, int, int, int) = nullptr; @@ -323,17 +324,41 @@ void align_image_level( \ } } - #ifndef NDEBUG - printf("%s::%s start: \n", __FILE__, __func__ ); - printf(" scale_factor_prev_curr %d, tile_size %d, prev_tile_size %d, search_radiou %d, distance L%d, \n", \ - scale_factor_prev_curr, curr_tile_size, prev_tile_size, search_radiou, distance_type ); - printf(" ref img size h=%d w=%d, alt img size h=%d w=%d, \n", \ - ref_img.size().height, ref_img.size().width, alt_img.size().height, alt_img.size().width ); - printf(" num tile h %d, num tile w %d\n", num_tiles_h, num_tiles_w); - #endif + // Every level share the same upsample function + void (*upsample_alignment_func_ptr)(std::vector>>&, std::vector>>&) = nullptr; + if ( scale_factor_prev_curr == 2 ) + { + if ( curr_tile_size / prev_tile_size == 2 ) + { + upsample_alignment_func_ptr = &build_upsampled_prev_aligement<2, 2>; + } + else if ( curr_tile_size / prev_tile_size == 1 ) + { + upsample_alignment_func_ptr = &build_upsampled_prev_aligement<2, 1>; + } + else + { + throw std::runtime_error("Something wrong with upsampling function setting\n"); + } + } + else if ( scale_factor_prev_curr == 4 ) + { + if ( curr_tile_size / prev_tile_size == 2 ) + { + upsample_alignment_func_ptr = &build_upsampled_prev_aligement<4, 2>; + } + else if ( curr_tile_size / prev_tile_size == 1 ) + { + upsample_alignment_func_ptr = &build_upsampled_prev_aligement<4, 1>; + } + else + { + throw std::runtime_error("Something wrong with upsampling function setting\n"); + } + } - printf("Reference image h=%d, w=%d: \n", ref_img.size().height, ref_img.size().width ); - print_img( ref_img ); + int num_tiles_ref_h = ref_img.size().height / (curr_tile_size / 2) - 1; + int num_tiles_ref_w = ref_img.size().width / (curr_tile_size / 2 ) - 1; /* Upsample pervious layer alignment */ std::vector>> upsampled_prev_aligement; @@ -342,28 +367,30 @@ void align_image_level( \ // prev_alignment is invalid / empty, construct alignment as (0,0) if ( prev_tile_size == -1 ) { - printf("create empty prev alignment\n"); - upsampled_prev_aligement.resize( num_tiles_h, std::vector>( num_tiles_w, std::pair(0, 0) ) ); + upsampled_prev_aligement.resize( num_tiles_ref_h, \ + std::vector>( num_tiles_ref_w, std::pair(0, 0) ) ); } // Upsample previous level alignment else { - if ( scale_factor_prev_curr == 2 ) - { - // TODO: add choose from 3 neighbour - upsample_alignment_stride<2>( prev_aligement, upsampled_prev_aligement ); - } - else if ( scale_factor_prev_curr == 4 ) - { - // TODO: add choose from 3 neighbour - upsample_alignment_stride<4>( prev_aligement, upsampled_prev_aligement ); - } - else - { - throw std::runtime_error("Invalid scale factor" + std::to_string( scale_factor_prev_curr ) ); - } + upsample_alignment_func_ptr( prev_aligement, upsampled_prev_aligement ); } + /* Basic infos */ + // NOTE: num_tile_h might be different from num_tile_ref_h + int num_tiles_h = upsampled_prev_aligement.size(); + int num_tiles_w = upsampled_prev_aligement.at(0).size(); + + #ifndef NDEBUG + printf("%s::%s start: \n", __FILE__, __func__ ); + printf(" scale_factor_prev_curr %d, tile_size %d, prev_tile_size %d, search_radiou %d, distance L%d, \n", \ + scale_factor_prev_curr, curr_tile_size, prev_tile_size, search_radiou, distance_type ); + printf(" ref img size h=%d w=%d, alt img size h=%d w=%d, \n", \ + ref_img.size().height, ref_img.size().width, alt_img.size().height, alt_img.size().width ); + printf(" num tile h (upsampled) %d, num tile w (upsampled) %d\n", num_tiles_h, num_tiles_w); + printf(" num tile h (gray) %d, num tile w (gray) %d\n", num_tiles_ref_h, num_tiles_ref_w); + #endif + // allocate memory for current alignmenr curr_alignment.resize( num_tiles_h, std::vector>( num_tiles_w, std::pair(0, 0) ) ); @@ -374,6 +401,9 @@ void align_image_level( \ search_radiou, search_radiou, search_radiou, search_radiou, \ cv::BORDER_CONSTANT, cv::Scalar( UINT_LEAST16_MAX ) ); + printf("Reference image h=%d, w=%d: \n", ref_img.size().height, ref_img.size().width ); + print_img( ref_img ); + printf("Alter image pad h=%d, w=%d: \n", alt_img_pad.size().height, alt_img_pad.size().width ); print_img( alt_img_pad ); @@ -382,6 +412,7 @@ void align_image_level( \ int alt_tile_row_idx_max = alt_img_pad.size().height - ( curr_tile_size + 2 * search_radiou ); int alt_tile_col_idx_max = alt_img_pad.size().width - ( curr_tile_size + 2 * search_radiou ); + // TODO delete below distance vector, this is for debug only std::vector> distances( num_tiles_h, std::vector( num_tiles_w, 0 )); /* Iterate through all reference tile & compute distance */ @@ -605,6 +636,7 @@ void align::process( const hdrplus::burst& burst_images, \ std::vector>> prev_alignment; for ( int level_i = num_levels - 1; level_i >= 0; level_i-- ) { + printf("\n\n########################align level %d\n", level_i ); align_image_level( ref_grayimg_pyramid[ level_i ], // reference image at current level alt_grayimg_pyramid[ level_i ], // alternative image at current level @@ -620,7 +652,9 @@ void align::process( const hdrplus::burst& burst_images, \ prev_alignment.swap( curr_alignment ); curr_alignment.clear(); - break; + // Stop at second iteration + if ( level_i == num_levels - 2 ) + break; } // for pyramid level