diff --git a/.gitignore b/.gitignore index 86ce44d..dd4eb87 100644 --- a/.gitignore +++ b/.gitignore @@ -56,4 +56,8 @@ tests/test_burst .vscode/ # VS Settings -CMakeSettings.json \ No newline at end of file +CMakeSettings.json + + +# Xiao local files +debug/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index d1b0313..e85b3bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,10 +4,10 @@ cmake_minimum_required(VERSION 3.0) project(hdrplus) # set c++ standard -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED True) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -march=native -O3") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -Wall -march=native -O3") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") # make sure we use Release and warn otherwise if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) @@ -24,7 +24,7 @@ else() endif() # require OpenCV -find_package( OpenCV 3 REQUIRED ) +find_package( OpenCV 4 REQUIRED ) include_directories( BEFORE ${OpenCV_INCLUDE_DIRS} ) message(STATUS "Found OpenCV ${OpenCV_INCLUDE_DIRS} ${OpenCV_LIBS}") @@ -37,13 +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 ) diff --git a/include/hdrplus/utility.h b/include/hdrplus/utility.h index ee87631..44b691f 100644 --- a/include/hdrplus/utility.h +++ b/include/hdrplus/utility.h @@ -127,4 +127,84 @@ cv::Mat downsample_nearest_neighbour( cv::Mat src_image ) return dst_image; } + +template< typename T > +void print_cvmat( cv::Mat image ) +{ + const T* img_ptr = (const T*)image.data; + int height = image.size().height; + int width = image.size().width; + int step = image.step1(); + + printf("print_cvmat()::Image of size height = %d, width = %d, step = %d\n", \ + height, width, step ); + + for ( int row_i = 0; row_i < height; ++row_i ) + { + int row_i_offset = row_i * step; + for ( int col_i = 0; col_i < width; ++col_i ) + { + printf("%3.d ", img_ptr[ row_i_offset + col_i ]); + //printf("%3.d ", int( image.at( row_i, col_i ) ) ); + } + printf("\n"); + } +} + + +/** + * @brief Extract RGB channel seprately from bayer image + * + * @tparam T data tyoe of bayer image. + * @return vector of RGB image. OpenCV internally maintain reference count. + * Thus this step won't create deep copy overhead. + * + * @example extract_rgb_fmom_bayer( bayer_img, rgb_vector_container ); + */ +template +void extract_rgb_fmom_bayer( const cv::Mat& bayer_img, \ + cv::Mat& red_img, cv::Mat& green_img1, cv::Mat& green_img2, cv::Mat& blue_img ) +{ + const T* bayer_img_ptr = (const T*)bayer_img.data; + int bayer_width = bayer_img.size().width; + int bayer_height = bayer_img.size().height; + int bayer_step = bayer_img.step1(); + + if ( bayer_width % 2 != 0 || bayer_height % 2 != 0 ) + { + throw std::runtime_error("Bayer image data size incorrect, must be multiplier of 2\n"); + } + + // RGB image is half the size of bayer image + int rgb_width = bayer_width / 2; + int rgb_height = bayer_height / 2; + red_img.create( rgb_height, rgb_width, bayer_img.type() ); + green_img1.create( rgb_height, rgb_width, bayer_img.type() ); + green_img2.create( rgb_height, rgb_width, bayer_img.type() ); + blue_img.create( rgb_height, rgb_width, bayer_img.type() ); + int rgb_step = red_img.step1(); + + T* r_img_ptr = (T*)red_img.data; + T* g1_img_ptr = (T*)green_img1.data; + T* g2_img_ptr = (T*)green_img2.data; + T* b_img_ptr = (T*)blue_img.data; + + for ( int rgb_row_i = 0; rgb_row_i < rgb_height; rgb_row_i++ ) + { + int rgb_row_i_offset = rgb_row_i * rgb_step; + + // Every RGB row corresbonding to two Bayer image row + int bayer_row_i_offset1 = ( rgb_row_i * 2 + 0 ) * bayer_step; // For RG + int bayer_row_i_offset2 = ( rgb_row_i * 2 + 1 ) * bayer_step; // For GB + + for ( int rgb_col_j = 0; rgb_col_j < rgb_width; rgb_col_j++ ) + { + r_img_ptr[ rgb_row_i_offset + rgb_col_j ] = bayer_img_ptr[ bayer_row_i_offset1 + ( rgb_col_j * 2 + 0 ) ]; + g1_img_ptr[ rgb_row_i_offset + rgb_col_j ] = bayer_img_ptr[ bayer_row_i_offset1 + ( rgb_col_j * 2 + 1 ) ]; + g2_img_ptr[ rgb_row_i_offset + rgb_col_j ] = bayer_img_ptr[ bayer_row_i_offset2 + ( rgb_col_j * 2 + 0 ) ]; + b_img_ptr[ rgb_row_i_offset + rgb_col_j ] = bayer_img_ptr[ bayer_row_i_offset2 + ( rgb_col_j * 2 + 1 ) ]; + } + } +} + } // namespace hdrplus diff --git a/tests/test_utility.cpp b/tests/test_utility.cpp index be12959..0c72ca2 100644 --- a/tests/test_utility.cpp +++ b/tests/test_utility.cpp @@ -1,31 +1,16 @@ #include #include +#include #include #include "hdrplus/utility.h" -template< typename T > -void print_cvmat( cv::Mat image ) -{ - int height = image.size().height; - int width = image.size().width; - - for ( int row_i = 0; row_i < height; ++row_i ) - { - for ( int col_i = 0; col_i < width; ++col_i ) - { - printf("%2.d ", int( image.at( row_i, col_i ) ) ); - } - printf("\n"); - } -} - void test_box_filter_2x2() { printf("\n###Test test_box_filter_2x2()###\n"); // Intialize input data int src_width = 10; int src_height = 6; - std::vector src_data( src_width, src_height ); + std::vector src_data( src_width * src_height ); for ( int i = 0; i < src_width * src_height; ++i ) { @@ -36,12 +21,14 @@ void test_box_filter_2x2() cv::Mat src_image( src_height, src_width, CV_16U, src_data.data() ); printf("src cv::Mat is \n"); - print_cvmat( src_image ); + hdrplus::print_cvmat( src_image ); cv::Mat dst_image = hdrplus::box_filter_2x2( src_image ); printf("dst cv::Mat is \n"); - print_cvmat( dst_image ); + hdrplus::print_cvmat( dst_image ); + + printf("test_box_filter_2x2 finish\n"); fflush(stdout); } void test_box_filter_kxk() @@ -50,7 +37,7 @@ void test_box_filter_kxk() // Intialize input data int src_width = 12; int src_height = 8; - std::vector src_data( src_width, src_height ); + std::vector src_data( src_width * src_height ); for ( int i = 0; i < src_width * src_height; ++i ) { @@ -61,17 +48,57 @@ void test_box_filter_kxk() cv::Mat src_image( src_height, src_width, CV_16U, src_data.data() ); printf("src cv::Mat is \n"); - print_cvmat( src_image ); + hdrplus::print_cvmat( src_image ); cv::Mat dst_image = hdrplus::box_filter_kxk( src_image ); printf("dst cv::Mat 2x2 is \n"); - print_cvmat( dst_image ); + hdrplus::print_cvmat( dst_image ); dst_image = hdrplus::box_filter_kxk( src_image ); printf("dst cv::Mat 4x4 is \n"); - print_cvmat( dst_image ); + hdrplus::print_cvmat( dst_image ); + + printf("test_box_filter_kxk finish\n"); fflush(stdout); +} + + +void test_extract_rgb_from_bayer() +{ + printf("\n###Test test_extract_rgb_from_bayer()###\n"); + // Intialize input data + int bayer_width = 24; + int bayer_height = 16; + std::vector bayer_data( bayer_width * bayer_height ); + + for ( int i = 0; i < bayer_width * bayer_height; ++i ) + { + bayer_data[ i ] = i+1; + } + + // Create input cv::mat + cv::Mat bayer_img = cv::Mat( bayer_height, bayer_width, CV_16U, bayer_data.data() ); + cv::Mat red_img, green_img1, green_img2, blue_img; + + printf("\nbayer cv::Mat is \n"); + hdrplus::print_cvmat( bayer_img ); + + hdrplus::extract_rgb_fmom_bayer( bayer_img, red_img, green_img1, green_img2, blue_img ); + + printf("\nRed cv::Mat is \n"); + hdrplus::print_cvmat( red_img ); + + printf("\nGreen 1 cv::Mat is \n"); + hdrplus::print_cvmat( green_img1 ); + + printf("\nGreen 2 cv::Mat is \n"); + hdrplus::print_cvmat( green_img2 ); + + printf("\nBlue cv::Mat is \n"); + hdrplus::print_cvmat( blue_img ); + + printf("test_extract_rgb_from_bayer finish\n"); fflush(stdout); } @@ -79,4 +106,7 @@ int main() { test_box_filter_2x2(); test_box_filter_kxk(); + test_extract_rgb_from_bayer(); + + printf("\ntest_utility finish\n"); } \ No newline at end of file