fix pyramid bug

main
Xiao Song 3 years ago
parent 98215ea914
commit c1b78d12e3

1
.gitignore vendored

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

@ -37,12 +37,6 @@ message(STATUS "Found LIBRAW_LIBRARY to be ${LIBRAW_LIBRARY}" )
find_package(exiv2 REQUIRED CONFIG NAMES exiv2)
message(STATUS "Found Exiv2 and linked")
if(NOT APPLE)
# The clang compiler (on osx) is somehow much more strict
# than the compilers on ubuntu and so this does not seem
# possible on OSX just yet.
add_definitions( -Werror )
endif()
# library
include_directories( include )

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

@ -53,7 +53,7 @@ cv::Mat box_filter_2x2( const cv::Mat& src_image )
}
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;
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>
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;
int src_height = src_image.size().height;
int src_width = src_image.size().width;
int src_step = src_image.step1();
if ( src_height % kernel != 0 || src_width % kernel != 0 )
{
throw std::runtime_error( std::string( __FILE__ ) + "::" + __func__ + " source image need to have size multiplier of kernel size\n" );
}
// int(src_height / kernel) = floor(src_height / kernel)
cv::Mat dst_image( src_height / kernel, src_width / kernel, src_image.type() );
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();
// -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 ) ] = \
src_image_ptr[ row_i * src_step + col_i ];
dst_image_ptr[ row_i * dst_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;
}

@ -17,12 +17,23 @@ static void build_per_grayimg_pyramid( \
const cv::Mat& src_image, \
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() );
cv::Mat blur_image;
cv::Mat downsample_image;
for ( int i = 0; i < inv_scale_factors.size(); ++i )
{
cv::Mat blur_image;
cv::Mat downsample_image;
printf("inv scale factor %d\n", inv_scale_factors.at( i ) );
switch ( inv_scale_factors[ i ] )
{
@ -32,9 +43,13 @@ static void build_per_grayimg_pyramid( \
downsample_image = src_image;
break;
case 2:
printf("gaussian blur 2 start\n"); fflush(stdout);
// 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_image = downsample_nearest_neighbour<uint16_t, 2>( blur_image );
@ -43,13 +58,19 @@ static void build_per_grayimg_pyramid( \
break;
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 );
images_pyramid[ images_pyramid.size() - i - 1 ] = downsample_image;
break;
default:
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>
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");
}
void align_image_level( \
const cv::Mat& ref_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, \
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
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 ][ 3 ] is the coarsest image
build_per_grayimg_pyramid( per_grayimg_pyramid[ img_idx ], \
burst_images.grayscale_images_pad[ img_idx ], \
inv_scale_factors );
build_per_grayimg_pyramid( per_grayimg_pyramid.at( img_idx ), \
burst_images.grayscale_images_pad.at( img_idx ), \
this->inv_scale_factors );
}
#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;
// 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
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 padding_top = 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 );
int padding_left = 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 );
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_pad[ 0 ].size().height, \
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
}

@ -9,6 +9,10 @@ void test_align_one_level(int argc, char** argv)
{
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] );
std::vector<std::vector<std::vector<std::pair<int, int>>>> alignments;

Loading…
Cancel
Save