2x2 box filter

main
Xiao Song 3 years ago
parent 8cb9bc8b59
commit f77f41c9c2

3
.gitignore vendored

@ -47,4 +47,5 @@ external/
dataset/
# Unit test
tests/test_bayer_image
tests/test_bayer_image
tests/test_utility

@ -61,3 +61,9 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/tests )
add_executable( test_bayer_image
tests/test_bayer_image.cpp )
target_link_libraries( test_bayer_image ${PROJECT_NAME} )
add_executable( test_utility
tests/test_utility.cpp )
target_link_libraries( test_utility
${OpenCV_LIBS}
${PROJECT_NAME} )

@ -14,9 +14,11 @@ class bayer_image
~bayer_image();
LibRaw libraw_processor;
cv::Mat image;
cv::Mat raw_image;
cv::Mat grayscale_image;
size_t width;
size_t height;
size_t white_level;
};
} // namespace hdrplus

@ -0,0 +1,49 @@
#pragma once
#include <string>
#include <stdexcept> // std::runtime_error
#include <opencv2/opencv.hpp> // all opencv header
// TODO: add openmp support
namespace hdrplus
{
template <typename T>
cv::Mat box_filter_2x2( cv::Mat src_image )
{
// https://stackoverflow.com/questions/34042112/opencv-mat-data-member-access
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 % 2 != 0 || src_width % 2 != 0 )
{
throw std::runtime_error( std::string( __FILE__ ) + "::" + __func__ + " source image need to have size multiplier of 2\n" );
}
cv::Mat dst_image( src_height / 2, src_width / 2, 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 += 2 )
{
for ( int col_i = 0; col_i < src_width; col_i += 2 )
{
T box_sum = src_image_ptr[ ( row_i + 0 ) * src_step + col_i + 0 ] + \
src_image_ptr[ ( row_i + 0 ) * src_step + col_i + 1 ] + \
src_image_ptr[ ( row_i + 1 ) * src_step + col_i + 0 ] + \
src_image_ptr[ ( row_i + 1 ) * src_step + col_i + 1 ];
T box_avg = ( box_sum + T(3) ) / 4; // take ceiling
dst_image_ptr[ ( row_i / 2 ) * dst_step + ( col_i / 2 ) ] = box_avg;
}
}
// cv::Mat internally use reference count. Will not copy by value here
return dst_image;
}
} // namespace hdrplus

@ -1,8 +1,10 @@
#include <string>
#include <cstdio>
#include <stdexcept> // std::runtime_error
#include <opencv2/opencv.hpp> // all opencv header
#include <libraw/libraw.h>
#include "hdrplus/bayer_image.h"
#include "hdrplus/utility.h" // box_filter_2x2
namespace hdrplus
{
@ -25,10 +27,20 @@ bayer_image::bayer_image( const std::string& bayer_image_path )
// Get image basic info
width = size_t( libraw_processor.imgdata.rawdata.sizes.raw_width );
height = size_t( libraw_processor.imgdata.rawdata.sizes.raw_height );
white_level = size_t( libraw_processor.imgdata.rawdata.color.maximum );
#ifndef NDEBUG
printf("%s::%s read bayer image %d with width %zu height %zu", \
__FILE__, __func__, bayer_image_path.c_str(), width, height );
#endif
// Create CV mat
// https://answers.opencv.org/question/105972/de-bayering-a-cr2-image/
image = cv::Mat( width, height, CV_16U, libraw_processor.imgdata.rawdata.raw_image );
// https://www.libraw.org/node/2141
raw_image = cv::Mat( width, height, CV_16U, libraw_processor.imgdata.rawdata.raw_image );
// 2x2 box filter
grayscale_image = box_filter_2x2<uint16_t>( raw_image );
}
bayer_image::~bayer_image()

@ -0,0 +1,49 @@
#include <cstdio>
#include <vector>
#include <opencv2/opencv.hpp>
#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<T>( row_i, col_i ) ) );
}
printf("\n");
}
}
void test_box_filter_2x2()
{
// Intialize input data
int src_width = 10;
int src_height = 6;
std::vector<uint16_t> src_data( src_width, src_height );
for ( int i = 0; i < src_width * src_height; ++i )
{
src_data[ i ] = i+1;
}
// Create input cv::mat
cv::Mat src_image( src_height, src_width, CV_16U, src_data.data() );
printf("src cv::Mat is \n");
print_cvmat<uint16_t>( src_image );
cv::Mat dst_image = hdrplus::box_filter_2x2<uint16_t>( src_image );
printf("dst cv::Mat is \n");
print_cvmat<uint16_t>( dst_image );
}
int main()
{
test_box_filter_2x2();
}
Loading…
Cancel
Save