diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a30263..b215501 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,9 +28,13 @@ find_package( OpenCV 4 REQUIRED ) include_directories( BEFORE ${OpenCV_INCLUDE_DIRS} ) message(STATUS "Found OpenCV ${OpenCV_INCLUDE_DIRS} ${OpenCV_LIBS}") -# LibRaw-cmake -find_library(LIBRAW_LIBRARY 0.20 NAMES raw raw_r) -include_directories( BEFORE "/usr/local/include/") +include_directories( BEFORE "/home/matthew/jniLibs/include/") +link_directories(/home/matthew/jniLibs/lib) +list(APPEND CMAKE_LIBRARY_PATH /home/matthew/jniLibs/lib/) + +# LibRaw-cmake 0.20 +# find_library(LIBRAW_LIBRARY raw /home/matthew/jniLibs/lib/) + message(STATUS "Found LIBRAW_LIBRARY to be ${LIBRAW_LIBRARY}" ) # Exiv2 @@ -55,15 +59,15 @@ set( src_files # Build runtime load dynamic shared library # https://cmake.org/cmake/help/latest/command/add_library.html -add_library(${PROJECT_NAME} SHARED ${src_files} ) +add_library(${PROJECT_NAME} STATIC ${src_files} ) # and link it # https://cmake.org/cmake/help/v3.0/command/target_link_libraries.html # use public because our .h / .hpp file include opencv .h / .hpp file target_link_libraries(${PROJECT_NAME} PUBLIC ${OpenCV_LIBS} - ${LIBRAW_LIBRARY} - exiv2lib + # ${LIBRAW_LIBRARY} + raw exiv2lib lcms2 OpenMP::OpenMP_CXX ) # example diff --git a/INSTALL.md b/INSTALL.md index ad9ee88..2f80433 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -24,7 +24,7 @@ Platform: Ubuntu 20.x step 4: `sudo make install` -3. Install `exiv2` : `apt install libexiv2-dev` +3. Install `exiv2`(exiv2-0.27.3.tar.gz) : `apt install libexiv2-dev` 4. Run CMake to build diff --git a/buildHdr.sh b/buildHdr.sh new file mode 100644 index 0000000..69c5e16 --- /dev/null +++ b/buildHdr.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +export INSTALL_DIR="`pwd`/jni/hdrplus" +export NDK=/usr/local/ndk/android-ndk-r25c +export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64 +export ABI=arm64-v8a +export MINSDKVERSION=24 +export JNILIBS_DIR=/home/matthew/jniLibs +# export EXPAT_DIR=/home/matthew/exiv2ForAndroid-master/expat-2.2.2/jni/expat + +mkdir -p $INSTALL_DIR +rm -rf build +mkdir -p build +cd build + +#SET(EXPAT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/expat/include ) +#SET(EXPAT_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/expat/lib/${ANDROID_ABI} ) + +cmake \ + -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \ + -DANDROID_ABI=$ABI \ + -DANDROID_NDK_ABI_NAME=$ABI \ + -DANDROID_PLATFORM=android-$MINSDKVERSION \ + -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR \ + -DBUILD_SHARED_LIBS=OFF \ + -DENABLE_EXAMPLES=OFF \ + -DHDRPLUS_NO_DETAILED_OUTPUT=1 \ + -DCMAKE_PREFIX_PATH=$JNILIBS_DIR/lib/$ABI/cmake \ + -DOpenCV_DIR=$JNILIBS_DIR/opencv-mobile-4.9.0-android/sdk/native/jni \ + -DLIBRAW_INCLUDE_DIR=$JNILIBS_DIR/include \ + -DLIBRAW_DIR=$JNILIBS_DIR/lib/cmake \ + -DJPEG_INCLUDE_DIR=$JNILIBS_DIR/include \ + -DJPEG_LIBRARIES=$JNILIBS_DIR/lib/$ABI \ + -Dexiv2_INCLUDE_DIR=$JNILIBS_DIR/include \ + -Dexiv2_DIR=$JNILIBS_DIR/lib/cmake/exiv2 \ + -DLCMS2_INCLUDE_DIR=$JNILIBS_DIR/include \ + -DLCMS2_LIBRARY=$JNILIBS_DIR/lib/$ABI \ + -DLCMS2_LIBRARIES=lcms2 \ + .. + + +make +# make install + diff --git a/include/hdrplus/burst.h b/include/hdrplus/burst.h index c4c9dda..b65c438 100644 --- a/include/hdrplus/burst.h +++ b/include/hdrplus/burst.h @@ -12,6 +12,8 @@ class burst { public: explicit burst( const std::string& burst_path, const std::string& reference_image_path ); + explicit burst(const std::vector& burst_paths, int reference_image_index); + ~burst() = default; // Reference image index in the array diff --git a/include/hdrplus/finish.h b/include/hdrplus/finish.h index 413ce0c..7fc68ae 100644 --- a/include/hdrplus/finish.h +++ b/include/hdrplus/finish.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -63,7 +64,7 @@ class finish // finish pipeline func // void process(std::string burstPath, cv::Mat mergedBayer,int refIdx); - void process(const hdrplus::burst& burst_images); + void process(const hdrplus::burst& burst_images, cv::Mat& finalOutputImage); // replace Mat a with Mat b void copy_mat_16U(cv::Mat& A, cv::Mat B); diff --git a/include/hdrplus/hdrplus_pipeline.h b/include/hdrplus/hdrplus_pipeline.h index 9df420a..e2fe100 100644 --- a/include/hdrplus/hdrplus_pipeline.h +++ b/include/hdrplus/hdrplus_pipeline.h @@ -19,6 +19,7 @@ class hdrplus_pipeline public: void run_pipeline( const std::string& burst_path, const std::string& reference_image_path ); + void run_pipeline( const std::vector& burst_paths, int reference_image_index, cv::Mat& finalImg ); hdrplus_pipeline() = default; ~hdrplus_pipeline() = default; }; diff --git a/include/hdrplus/params.h b/include/hdrplus/params.h index c2f6476..96bb2c9 100644 --- a/include/hdrplus/params.h +++ b/include/hdrplus/params.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include // std::shared_ptr #include // all opencv header #include diff --git a/src/bayer_image.cpp b/src/bayer_image.cpp index c5bfced..53a34b2 100644 --- a/src/bayer_image.cpp +++ b/src/bayer_image.cpp @@ -1,5 +1,6 @@ #include #include +#include #include // std::pair, std::makr_pair #include // std::shared_ptr #include // std::runtime_error diff --git a/src/burst.cpp b/src/burst.cpp index 5aec7b7..ad4e63c 100644 --- a/src/burst.cpp +++ b/src/burst.cpp @@ -101,4 +101,79 @@ burst::burst( const std::string& burst_path, const std::string& reference_image_ #endif } +burst::burst( const std::vector& bayer_image_paths, int reference_image_index ) +{ + // Number of images + num_images = bayer_image_paths.size(); + + // Find reference image path in input directory + // reference image path need to be absolute path + reference_image_idx = -1; + if ( reference_image_index > 0 && reference_image_index < bayer_image_paths.size() ) + { + reference_image_idx = reference_image_index; + } + + if ( reference_image_idx == -1 ) + { + throw std::runtime_error("Error reference image index is out of range " ); + } + + #ifndef NDEBUG + for ( const auto& bayer_image_path_i : bayer_image_paths ) + { + printf("%s::%s Find image %s\n", \ + __FILE__, __func__, bayer_image_path_i.c_str()); + } + + printf("%s::%s reference image idx %d\n", \ + __FILE__, __func__, reference_image_idx ); + #endif + + // Get source bayer image + // Downsample original bayer image by 2x2 box filter + for ( const auto& bayer_image_path_i : bayer_image_paths ) + { + bayer_images.emplace_back( bayer_image_path_i ); + } + + // Pad information + 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 ? \ + 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 ? \ + 0 : tile_size_bayer - bayer_images[ 0 ].width % tile_size_bayer ); + padding_info_bayer = std::vector{ padding_top, padding_bottom, padding_left, padding_right }; + + // Pad bayer image + for ( const auto& bayer_image_i : bayer_images ) + { + cv::Mat bayer_image_pad_i; + cv::copyMakeBorder( bayer_image_i.raw_image, \ + bayer_image_pad_i, \ + padding_top, padding_bottom, padding_left, padding_right, \ + cv::BORDER_REFLECT ); + + // cv::Mat use internal reference count + bayer_images_pad.emplace_back( bayer_image_pad_i ); + grayscale_images_pad.emplace_back( box_filter_kxk( bayer_image_pad_i ) ); + } + + #ifndef NDEBUG + printf("%s::%s Pad bayer image from (%d, %d) -> (%d, %d)\n", \ + __FILE__, __func__, \ + bayer_images[ 0 ].height, \ + 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 +} + } // namespace hdrplus diff --git a/src/finish.cpp b/src/finish.cpp index 64e3f91..6a9e1b7 100644 --- a/src/finish.cpp +++ b/src/finish.cpp @@ -1,3 +1,4 @@ +#include #include // all opencv header #include "hdrplus/finish.h" #include "hdrplus/utility.h" @@ -554,23 +555,29 @@ namespace hdrplus myfile.close(); } - void finish::process(const hdrplus::burst& burst_images){ + void finish::process(const hdrplus::burst& burst_images, cv::Mat& finalOutputImage){ // copy mergedBayer to rawReference std::cout<<"finish pipeline start ..."<refIdx = burst_images.reference_image_idx; // this->burstPath = burstPath; // std::cout<<"processMerged:"<mergedBayer = processMergedMat(mergedB,CV_16UC1);//loadFromCSV("merged.csv", CV_16UC1); // std::cout<<"processMerged:"<mergedBayer); this->mergedBayer = loadFromCSV("merged.csv", CV_16UC1); - +#else + this->mergedBayer = processMergedMat(burst_images.merged_bayer_image, CV_16UC1); + // std::cout<<"processMerged:"<mergedBayer); // load_rawPathList(burstPath); @@ -585,7 +592,8 @@ namespace hdrplus std::cout<<"size ref: "<libraw_processor,params.rawpyArgs); // write merged image +#ifndef HDRPLUS_NO_DETAILED_OUTPUT if(params.flags["writeMergedImage"]){ std::cout<<"writing Merged img ..."<& burst_paths, \ + int reference_image_index, cv::Mat& finalImg ) +{ + // Create burst of images + burst burst_images( burst_paths, reference_image_index ); + std::vector>>> alignments; + + // Run align + align_module.process( burst_images, alignments ); + + // Run merging + merge_module.process( burst_images, alignments ); + + // Run finishing + finish_module.process( burst_images, finalImg); } } // namespace hdrplus diff --git a/src/params.cpp b/src/params.cpp index 0a0d39b..889bff1 100644 --- a/src/params.cpp +++ b/src/params.cpp @@ -1,3 +1,4 @@ +#include #include // all opencv header #include