fix pyramid bug

main
Xiao Song 3 years ago
parent e473ed5ebd
commit 14d7a409e3

1
.gitignore vendored

@ -50,6 +50,7 @@ dataset/
tests/test_bayer_image tests/test_bayer_image
tests/test_utility tests/test_utility
tests/test_burst tests/test_burst
tests/test_align
# VS/VSCode folder # VS/VSCode folder
.vs/ .vs/

@ -5,7 +5,6 @@
#include <opencv2/opencv.hpp> // all opencv header #include <opencv2/opencv.hpp> // all opencv header
#include <libraw/libraw.h> #include <libraw/libraw.h>
namespace hdrplus namespace hdrplus
{ {
class RawpyArgs{ class RawpyArgs{

@ -53,7 +53,7 @@ cv::Mat box_filter_2x2( const cv::Mat& src_image )
} }
template <typename T, int kernel> template <typename T, int kernel>
cv::Mat box_filter_kxk( cv::Mat src_image ) cv::Mat box_filter_kxk( const cv::Mat& src_image )
{ {
const T* src_image_ptr = (T*)src_image.data; const T* src_image_ptr = (T*)src_image.data;
int src_height = src_image.size().height; int src_height = src_image.size().height;
@ -97,33 +97,31 @@ cv::Mat box_filter_kxk( cv::Mat src_image )
template <typename T, int kernel> template <typename T, int kernel>
cv::Mat downsample_nearest_neighbour( cv::Mat src_image ) cv::Mat downsample_nearest_neighbour( const cv::Mat& src_image )
{ {
const T* src_image_ptr = (T*)src_image.data; const T* src_image_ptr = (T*)src_image.data;
int src_height = src_image.size().height; int src_height = src_image.size().height;
int src_width = src_image.size().width; int src_width = src_image.size().width;
int src_step = src_image.step1(); int src_step = src_image.step1();
if ( src_height % kernel != 0 || src_width % kernel != 0 ) // int(src_height / kernel) = floor(src_height / kernel)
{
throw std::runtime_error( std::string( __FILE__ ) + "::" + __func__ + " source image need to have size multiplier of kernel size\n" );
}
cv::Mat dst_image( src_height / kernel, src_width / kernel, src_image.type() ); cv::Mat dst_image( src_height / kernel, src_width / kernel, src_image.type() );
T* dst_image_ptr = (T*)dst_image.data; T* dst_image_ptr = (T*)dst_image.data;
int dst_height = dst_image.size().height;
int dst_width = dst_image.size().width;
int dst_step = dst_image.step1(); int dst_step = dst_image.step1();
// -03 should be enough to optimize below code // -03 should be enough to optimize below code
for ( int row_i = 0; row_i < src_height; row_i += kernel ) for ( int row_i = 0; row_i < dst_height; row_i += kernel )
{ {
for ( int col_i = 0; col_i < src_width; col_i += kernel ) for ( int col_i = 0; col_i < dst_width; col_i += kernel )
{ {
dst_image_ptr[ ( row_i / kernel ) * dst_step + ( col_i / kernel ) ] = \ dst_image_ptr[ row_i * dst_step + col_i ] = \
src_image_ptr[ row_i * src_step + col_i ]; src_image_ptr[ (row_i * kernel) * src_step + (col_i * kernel) ];
} }
} }
// cv::Mat internally use reference count. Will not copy by value here // cv::Mat internally use reference count. Will not copy by value (deepcopy) here
return dst_image; return dst_image;
} }

@ -17,12 +17,23 @@ static void build_per_grayimg_pyramid( \
const cv::Mat& src_image, \ const cv::Mat& src_image, \
const std::vector<int>& inv_scale_factors ) const std::vector<int>& inv_scale_factors )
{ {
#ifndef NDEBUG
printf("%s::%s build_per_grayimg_pyramid start with scale factor : ", __FILE__, __func__ );
for ( int i = 0; i < inv_scale_factors.size(); ++i )
{
printf("%d ", inv_scale_factors.at( i ));
}
printf("\n");
#endif
images_pyramid.resize( inv_scale_factors.size() ); images_pyramid.resize( inv_scale_factors.size() );
cv::Mat blur_image;
cv::Mat downsample_image;
for ( int i = 0; i < inv_scale_factors.size(); ++i ) for ( int i = 0; i < inv_scale_factors.size(); ++i )
{ {
cv::Mat blur_image; printf("inv scale factor %d\n", inv_scale_factors.at( i ) );
cv::Mat downsample_image;
switch ( inv_scale_factors[ i ] ) switch ( inv_scale_factors[ i ] )
{ {
@ -32,9 +43,13 @@ static void build_per_grayimg_pyramid( \
downsample_image = src_image; downsample_image = src_image;
break; break;
case 2: case 2:
printf("gaussian blur 2 start\n"); fflush(stdout);
// Gaussian blur // Gaussian blur
cv::GaussianBlur( downsample_image, blur_image, cv::Size(0, 0), 1.0 ); cv::GaussianBlur( downsample_image, blur_image, cv::Size(0, 0), inv_scale_factors[ i ] / 2 );
printf("gaussian blur 2 done\n"); fflush(stdout);
// Downsample // Downsample
downsample_image = downsample_nearest_neighbour<uint16_t, 2>( blur_image ); downsample_image = downsample_nearest_neighbour<uint16_t, 2>( blur_image );
@ -43,13 +58,19 @@ static void build_per_grayimg_pyramid( \
break; break;
case 4: case 4:
cv::GaussianBlur( downsample_image, blur_image, cv::Size(0, 0), 2.0 ); printf("gaussian blur 4 start\n"); fflush(stdout);
cv::GaussianBlur( downsample_image, blur_image, cv::Size(0, 0), inv_scale_factors[ i ] / 2 );
printf("gaussian blur 4 done\n"); fflush(stdout);
downsample_image = downsample_nearest_neighbour<uint16_t, 4>( blur_image ); downsample_image = downsample_nearest_neighbour<uint16_t, 4>( blur_image );
images_pyramid[ images_pyramid.size() - i - 1 ] = downsample_image; images_pyramid[ images_pyramid.size() - i - 1 ] = downsample_image;
break; break;
default: default:
throw std::runtime_error("inv scale factor " + std::to_string( inv_scale_factors[ i ]) + "invalid" ); throw std::runtime_error("inv scale factor " + std::to_string( inv_scale_factors[ i ]) + "invalid" );
} }
printf("downsample size h=%d w=%d\n", \
downsample_image.size().height, downsample_image.size().width ); fflush(stdout);
} }
} }
@ -90,6 +111,7 @@ static void upsample_alignment_stride( \
} }
} }
template <typename T> template <typename T>
void print_tile( const cv::Mat& img, int tile_size, int start_idx_x, int start_idx_y ) void print_tile( const cv::Mat& img, int tile_size, int start_idx_x, int start_idx_y )
{ {
@ -110,6 +132,7 @@ void print_tile( const cv::Mat& img, int tile_size, int start_idx_x, int start_i
printf("\n"); printf("\n");
} }
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, \
@ -230,6 +253,10 @@ static void build_per_pyramid_reftiles_start( \
void align::process( const hdrplus::burst& burst_images, \ void align::process( const hdrplus::burst& burst_images, \
std::vector<std::vector<std::vector<std::pair<int, int>>>>& images_alignment ) std::vector<std::vector<std::vector<std::pair<int, int>>>>& images_alignment )
{ {
#ifndef NDEBUG
printf("%s::%s align::process start\n", __FILE__, __func__ );
#endif
// image pyramid per image, per pyramid level // image pyramid per image, per pyramid level
std::vector<std::vector<cv::Mat>> per_grayimg_pyramid; std::vector<std::vector<cv::Mat>> per_grayimg_pyramid;
@ -238,9 +265,9 @@ void align::process( const hdrplus::burst& burst_images, \
{ {
// per_grayimg_pyramid[ img_idx ][ 0 ] is the original image // per_grayimg_pyramid[ img_idx ][ 0 ] is the original image
// per_grayimg_pyramid[ img_idx ][ 3 ] is the coarsest image // per_grayimg_pyramid[ img_idx ][ 3 ] is the coarsest image
build_per_grayimg_pyramid( per_grayimg_pyramid[ img_idx ], \ build_per_grayimg_pyramid( per_grayimg_pyramid.at( img_idx ), \
burst_images.grayscale_images_pad[ img_idx ], \ burst_images.grayscale_images_pad.at( img_idx ), \
inv_scale_factors ); this->inv_scale_factors );
} }
#ifndef NDEBUG #ifndef NDEBUG

@ -11,7 +11,18 @@ burst::burst( const std::string& burst_path, const std::string& reference_image_
{ {
std::vector<cv::String> bayer_image_paths; std::vector<cv::String> bayer_image_paths;
// Search through the input path directory to get all input image path // Search through the input path directory to get all input image path
cv::glob( burst_path + "/*.dng", bayer_image_paths, false ); if ( burst_path.at( burst_path.size() - 1) == '/')
cv::glob( burst_path + "*.dng", bayer_image_paths, false );
else
cv::glob( burst_path + "/*.dng", bayer_image_paths, false );
#ifndef NDEBUG
for ( const auto& bayer_img_path_i : bayer_image_paths )
{
printf("img i path %s\n", bayer_img_path_i.c_str()); fflush(stdout);
}
printf("ref img path %s\n", reference_image_path.c_str()); fflush(stdout);
#endif
// Number of images // Number of images
num_images = bayer_image_paths.size(); num_images = bayer_image_paths.size();
@ -54,11 +65,11 @@ burst::burst( const std::string& burst_path, const std::string& reference_image_
int tile_size_bayer = 32; int tile_size_bayer = 32;
int padding_top = tile_size_bayer / 2; int padding_top = tile_size_bayer / 2;
int padding_bottom = tile_size_bayer / 2 + \ int padding_bottom = tile_size_bayer / 2 + \
( bayer_images[ 0 ].height % tile_size_bayer == 0 ? \ ( (bayer_images[ 0 ].height % tile_size_bayer) == 0 ? \
0 : tile_size_bayer - bayer_images[ 0 ].height % tile_size_bayer ); 0 : tile_size_bayer - bayer_images[ 0 ].height % tile_size_bayer );
int padding_left = tile_size_bayer / 2; int padding_left = tile_size_bayer / 2;
int padding_right = tile_size_bayer / 2 + \ int padding_right = tile_size_bayer / 2 + \
( bayer_images[ 0 ].width % tile_size_bayer == 0 ? \ ( (bayer_images[ 0 ].width % tile_size_bayer) == 0 ? \
0 : tile_size_bayer - bayer_images[ 0 ].width % tile_size_bayer ); 0 : tile_size_bayer - bayer_images[ 0 ].width % tile_size_bayer );
padding_info_bayer = std::vector<int>{ padding_top, padding_bottom, padding_left, padding_right }; padding_info_bayer = std::vector<int>{ padding_top, padding_bottom, padding_left, padding_right };
@ -83,6 +94,9 @@ burst::burst( const std::string& burst_path, const std::string& reference_image_
bayer_images[ 0 ].width, \ bayer_images[ 0 ].width, \
bayer_images_pad[ 0 ].size().height, \ bayer_images_pad[ 0 ].size().height, \
bayer_images_pad[ 0 ].size().width ); bayer_images_pad[ 0 ].size().width );
printf("%s::%s pad top %d, buttom %d, left %d, right %d\n", \
__FILE__, __func__, \
padding_top, padding_bottom, padding_left, padding_right );
#endif #endif
} }

@ -9,6 +9,10 @@ void test_align_one_level(int argc, char** argv)
{ {
printf("Usage ./test_align BUTST_PATH REF_PATH"); printf("Usage ./test_align BUTST_PATH REF_PATH");
} }
printf("Burst img dir %s\n", argv[1]);
printf("Ref img path %s\n", argv[2]);
hdrplus::burst burst_images( argv[1], argv[2] ); hdrplus::burst burst_images( argv[1], argv[2] );
std::vector<std::vector<std::vector<std::pair<int, int>>>> alignments; std::vector<std::vector<std::vector<std::pair<int, int>>>> alignments;

Loading…
Cancel
Save